aboutsummaryrefslogtreecommitdiff
path: root/contrib/loaders/flash/dw-spi
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/loaders/flash/dw-spi')
-rw-r--r--contrib/loaders/flash/dw-spi/Makefile35
-rw-r--r--contrib/loaders/flash/dw-spi/dw-spi.c246
-rw-r--r--contrib/loaders/flash/dw-spi/dw-spi.h313
-rw-r--r--contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc39
-rw-r--r--contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc39
-rw-r--r--contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc51
-rw-r--r--contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc33
-rw-r--r--contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc21
8 files changed, 777 insertions, 0 deletions
diff --git a/contrib/loaders/flash/dw-spi/Makefile b/contrib/loaders/flash/dw-spi/Makefile
new file mode 100644
index 0000000..e868278
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/Makefile
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+TOOLCHAIN:=mipsel-linux-gnu-
+CC:=$(TOOLCHAIN)gcc
+OBJCOPY:=$(TOOLCHAIN)objcopy
+CFLAGS:=-O2 -Wall -Wextra -fpic -Wno-int-to-pointer-cast
+SRC=dw-spi.c
+OBJ=$(patsubst %.c, %.o,$(SRC))
+
+# sparx-iv
+ifeq ($(TOOLCHAIN),mipsel-linux-gnu-)
+ CFLAGS+= -march=24kec
+endif
+
+all: \
+ $(TOOLCHAIN)transaction.inc \
+ $(TOOLCHAIN)erase.inc \
+ $(TOOLCHAIN)check_fill.inc \
+ $(TOOLCHAIN)program.inc \
+ $(TOOLCHAIN)read.inc
+
+$(TOOLCHAIN)%.bin: $(OBJ)
+ $(OBJCOPY) --dump-section .$*=$@ $<
+
+%.inc: %.bin
+ xxd -i > $@ < $<
+
+.PHONY: clean
+clean:
+ rm -rf .ccls-cache
+ find . \( \
+ -iname "*.o" \
+ -o -iname "*.bin" \
+ -o -iname "*.inc" \
+ \) -delete
diff --git a/contrib/loaders/flash/dw-spi/dw-spi.c b/contrib/loaders/flash/dw-spi/dw-spi.c
new file mode 100644
index 0000000..66b7439
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/dw-spi.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/**
+ * @file
+ * Helper functions for DesignWare SPI Core driver.
+ * These helpers are loaded into CPU and execute Flash manipulation algorithms
+ * at full CPU speed. Due to inability to control nCS pin, this is the only way
+ * to communicate with Flash chips connected via DW SPI serial interface.
+ *
+ * In order to avoid using stack, all functions used in helpers are inlined.
+ * Software breakpoints are used to terminate helpers.
+ *
+ * Pushing byte to TX FIFO does not make byte immediately available in RX FIFO
+ * and nCS is only asserted when TX FIFO is not empty. General approach is to
+ * fill TX FIFO with as many bytes as possible, at the same time reading
+ * available bytes from RX FIFO.
+ *
+ * This file contains helper functions.
+ */
+
+#include "dw-spi.h"
+
+#include "../../../../src/flash/nor/dw-spi-helper.h"
+
+/**
+ * @brief Generic flash transaction.
+ *
+ * @param[in] arg: Function arguments.
+ */
+__attribute__((section(".transaction"))) void
+transaction(struct dw_spi_transaction *arg)
+{
+ register uint8_t *buffer_tx = (uint8_t *)arg->buffer;
+ register uint8_t *buffer_rx = buffer_tx;
+ register uint32_t size = arg->size;
+ register volatile uint8_t *status = (uint8_t *)arg->status_reg;
+ register volatile uint8_t *data = (uint8_t *)arg->data_reg;
+
+ wait_tx_finish(status);
+ flush_rx(status, data);
+
+ for (; size > 0; size--) {
+ send_u8(status, data, *buffer_tx++);
+ if (arg->read_flag && rx_available(status))
+ *buffer_rx++ = rcv_byte(data);
+ }
+
+ // Pushed all data to TX FIFO. Read bytes left in RX FIFO.
+ if (arg->read_flag) {
+ while (buffer_rx < buffer_tx) {
+ wait_rx_available(status);
+ *buffer_rx++ = rcv_byte(data);
+ }
+ }
+
+ RETURN;
+}
+
+/**
+ * @brief Check flash sectors are filled with pattern. Primary use for
+ * checking sector erase state.
+ *
+ * @param[in] arg: Function arguments.
+ */
+__attribute__((section(".check_fill"))) void
+check_fill(struct dw_spi_check_fill *arg)
+{
+ register uint32_t tx_size;
+ register uint32_t rx_size;
+ register uint32_t dummy_count;
+ register uint8_t filled;
+ register uint8_t *fill_status_array = (uint8_t *)arg->fill_status_array;
+ register volatile uint8_t *status = (uint8_t *)arg->status_reg;
+ register volatile uint8_t *data = (uint8_t *)arg->data_reg;
+
+ for (; arg->sector_count > 0; arg->sector_count--,
+ arg->address += arg->sector_size,
+ fill_status_array++) {
+ wait_tx_finish(status);
+ flush_rx(status, data);
+
+ /*
+ * Command byte and address bytes make up for dummy_count number of
+ * bytes, that must be skipped in RX FIFO before actual data arrives.
+ */
+ send_u8(status, data, arg->read_cmd);
+ if (arg->four_byte_mode) {
+ dummy_count = 1 + 4; // Command byte + 4 address bytes
+ send_u32(status, data, arg->address);
+ } else {
+ dummy_count = 1 + 3; // Command byte + 3 address bytes
+ send_u24(status, data, arg->address);
+ }
+
+ for (tx_size = arg->sector_size, rx_size = arg->sector_size, filled = 1;
+ tx_size > 0; tx_size--) {
+ send_u8(status, data, 0); // Dummy write to push out read data.
+ if (rx_available(status)) {
+ if (dummy_count > 0) {
+ // Read data not arrived yet.
+ rcv_byte(data);
+ dummy_count--;
+ } else {
+ if (rcv_byte(data) != arg->pattern) {
+ filled = 0;
+ break;
+ }
+ rx_size--;
+ }
+ }
+ }
+ if (filled) {
+ for (; rx_size > 0; rx_size--) {
+ wait_rx_available(status);
+ if (rcv_byte(data) != arg->pattern) {
+ filled = 0;
+ break;
+ }
+ }
+ }
+ *fill_status_array = filled;
+ }
+
+ RETURN;
+}
+
+/**
+ * @brief Erase flash sectors.
+ *
+ * @param[in] arg: Function arguments.
+ */
+__attribute__((section(".erase"))) void
+erase(struct dw_spi_erase *arg)
+{
+ register uint32_t address = arg->address;
+ register uint32_t count = arg->sector_count;
+ register volatile uint8_t *status = (uint8_t *)arg->status_reg;
+ register volatile uint8_t *data = (uint8_t *)arg->data_reg;
+
+ for (; count > 0; count--, address += arg->sector_size) {
+ write_enable(status, data, arg->write_enable_cmd);
+ wait_write_enable(status, data, arg->read_status_cmd,
+ arg->write_enable_mask);
+
+ erase_sector(status, data, arg->erase_sector_cmd, address,
+ arg->four_byte_mode);
+ wait_busy(status, data, arg->read_status_cmd, arg->busy_mask);
+ }
+
+ RETURN;
+}
+
+/**
+ * @brief Flash program.
+ *
+ * @param[in] arg: Function arguments.
+ */
+__attribute__((section(".program"))) void
+program(struct dw_spi_program *arg)
+{
+ register uint8_t *buffer = (uint8_t *)arg->buffer;
+ register uint32_t buffer_size = arg->buffer_size;
+ register volatile uint8_t *status = (uint8_t *)arg->status_reg;
+ register volatile uint8_t *data = (uint8_t *)arg->data_reg;
+ register uint32_t page_size;
+
+ while (buffer_size > 0) {
+ write_enable(status, data, arg->write_enable_cmd);
+ wait_write_enable(status, data, arg->read_status_cmd,
+ arg->write_enable_mask);
+
+ wait_tx_finish(status);
+
+ send_u8(status, data, arg->program_cmd);
+ if (arg->four_byte_mode)
+ send_u32(status, data, arg->address);
+ else
+ send_u24(status, data, arg->address);
+
+ for (page_size = MIN(arg->page_size, buffer_size); page_size > 0;
+ page_size--, buffer_size--) {
+ send_u8(status, data, *buffer++);
+ }
+ arg->address += arg->page_size;
+ wait_busy(status, data, arg->read_status_cmd, arg->busy_mask);
+ }
+
+ RETURN;
+}
+
+/**
+ * @brief Read data from flash.
+ *
+ * @param[in] arg: Function arguments.
+ */
+__attribute__((section(".read"))) void
+read(struct dw_spi_read *arg)
+{
+ register uint32_t tx_size = arg->buffer_size;
+ register uint32_t rx_size = arg->buffer_size;
+ register uint32_t dummy_count;
+ register uint8_t *buffer = (uint8_t *)arg->buffer;
+ register volatile uint8_t *status = (uint8_t *)arg->status_reg;
+ register volatile uint8_t *data = (uint8_t *)arg->data_reg;
+
+ wait_tx_finish(status);
+ flush_rx(status, data);
+
+ /*
+ * Command byte and address bytes make up for dummy_count number of
+ * bytes, that must be skipped in RX FIFO before actual data arrives.
+ */
+ send_u8(status, data, arg->read_cmd);
+ if (arg->four_byte_mode) {
+ dummy_count = 1 + 4; // Command byte + 4 address bytes
+ send_u32(status, data, arg->address);
+ } else {
+ dummy_count = 1 + 3; // Command byte + 3 address bytes
+ send_u24(status, data, arg->address);
+ }
+
+ for (; tx_size > 0; tx_size--) {
+ send_u8(status, data, 0); // Dummy write to push out read data.
+ if (rx_available(status)) {
+ if (dummy_count > 0) {
+ rcv_byte(data);
+ dummy_count--;
+ } else {
+ *buffer++ = rcv_byte(data);
+ rx_size--;
+ }
+ }
+ }
+ while (rx_size > 0) {
+ wait_rx_available(status);
+ if (dummy_count > 0) {
+ // Read data not arrived yet.
+ rcv_byte(data);
+ dummy_count--;
+ } else {
+ *buffer++ = rcv_byte(data);
+ rx_size--;
+ }
+ }
+
+ RETURN;
+}
diff --git a/contrib/loaders/flash/dw-spi/dw-spi.h b/contrib/loaders/flash/dw-spi/dw-spi.h
new file mode 100644
index 0000000..9efa768
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/dw-spi.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/**
+ * @file
+ * Helper functions for DesignWare SPI Core driver.
+ * These helpers are loaded into CPU and execute Flash manipulation algorithms
+ * at full CPU speed. Due to inability to control nCS pin, this is the only way
+ * to communicate with Flash chips connected via DW SPI serial interface.
+ *
+ * In order to avoid using stack, all functions used in helpers are inlined.
+ * Software breakpoints are used to terminate helpers.
+ *
+ * This file contains functions, common to helpers.
+ */
+
+#ifndef _DW_SPI_H_
+#define _DW_SPI_H_
+
+#include <stdint.h>
+#include <sys/param.h>
+
+#include "../../../../src/helper/types.h"
+
+/**
+ * @brief SI busy status bit.
+ *
+ * Set when serial transfer is in progress, cleared when master is idle or
+ * disabled.
+ */
+#define DW_SPI_STATUS_BUSY 0x01
+
+/**
+ * @brief SI TX FIFO not full status bit.
+ *
+ * Set when TX FIFO has room for one or more data-word.
+ */
+#define DW_SPI_STATUS_TFNF 0x02
+
+/**
+ * @brief SI TX FIFO empty status bit.
+ */
+#define DW_SPI_STATUS_TFE 0x04
+
+/**
+ * @brief SI RX FIFO not empty status bit.
+ */
+#define DW_SPI_STATUS_RFNE 0x08
+
+/**
+ * @brief Return from helper function.
+ */
+#define RETURN \
+ do { \
+ asm("sdbbp\n\t"); \
+ return; \
+ } while (0)
+
+/**
+ * @brief Append byte to TX FIFO.
+ *
+ * For each transferred byte, DW SPI controller receives a byte into RX FIFO.
+ * Slave data are read by pushing dummy bytes to TX FIFO.
+ *
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] byte: Data to push.
+ */
+__attribute__((always_inline)) static inline void
+_send_byte(volatile uint8_t *dr, uint8_t byte)
+{
+ *dr = byte;
+}
+
+/**
+ * @brief Get byte from RX FIFO.
+ *
+ * Reading RX byte removes it from RX FIFO.
+ *
+ * @param[in] dr: Pointer to DR register.
+ * @return RX FIFO byte.
+ */
+__attribute__((always_inline)) static inline uint8_t
+rcv_byte(volatile uint8_t *dr)
+{
+ return *dr;
+}
+
+/**
+ * @brief Check transmission is currently in progress.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @retval 1: Transmission is in progress.
+ * @retval 0: Controller is idle or off.
+ */
+__attribute__((always_inline)) static inline int
+tx_in_progress(volatile uint8_t *sr)
+{
+ return (*sr ^ DW_SPI_STATUS_TFE) & (DW_SPI_STATUS_BUSY | DW_SPI_STATUS_TFE);
+}
+
+/**
+ * @brief Wait for controller to finish previous transaction.
+ *
+ * @param[in] sr: Pointer to SR register.
+ */
+__attribute__((always_inline)) static inline void
+wait_tx_finish(volatile uint8_t *sr)
+{
+ while (tx_in_progress(sr))
+ ;
+}
+
+/**
+ * @brief Wait for room in TX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ */
+__attribute__((always_inline)) static inline void
+wait_tx_available(volatile uint8_t *sr)
+{
+ while (!(*sr & DW_SPI_STATUS_TFNF))
+ ;
+}
+
+/**
+ * @brief Check for data available in RX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @retval 1: Data available.
+ * @retval 0: No data available.
+ */
+__attribute__((always_inline)) static inline int
+rx_available(volatile uint8_t *sr)
+{
+ return *sr & DW_SPI_STATUS_RFNE;
+}
+
+/**
+ * @brief Wait for data in RX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ */
+__attribute__((always_inline)) static inline void
+wait_rx_available(volatile uint8_t *sr)
+{
+ while (!rx_available(sr))
+ ;
+}
+
+/**
+ * @brief Flush RX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ */
+__attribute__((always_inline)) static inline void
+flush_rx(volatile uint8_t *sr, volatile uint8_t *dr)
+{
+ while (*sr & DW_SPI_STATUS_RFNE)
+ *dr;
+}
+
+/**
+ * @brief Append variable number of bytes to TX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] word: Data to append.
+ * @param[in] bytes: Number of bytes to append.
+ */
+__attribute__((always_inline)) static inline void
+_send_bytes(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word,
+ int bytes)
+{
+ for (register int i = bytes - 1; i >= 0; i--) {
+ wait_tx_available(sr);
+ _send_byte(dr, (word >> (i * 8)) & 0xff);
+ }
+}
+
+/**
+ * @brief Append 8 bit value to TX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] word: Data to push.
+ */
+__attribute__((always_inline)) static inline void
+send_u8(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t byte)
+{
+ wait_tx_available(sr);
+ _send_byte(dr, byte);
+}
+
+/**
+ * @brief Append 24 bit value to TX FIFO.
+ *
+ * Used to send Flash addresses in 24 bit mode.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] word: Data to push.
+ */
+__attribute__((always_inline)) static inline void
+send_u24(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word)
+{
+ _send_bytes(sr, dr, word, 3);
+}
+
+/**
+ * @brief Append 32 bit value to TX FIFO.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] word: Data to push.
+ */
+__attribute__((always_inline)) static inline void
+send_u32(volatile uint8_t *sr, volatile uint8_t *dr, uint32_t word)
+{
+ _send_bytes(sr, dr, word, 4);
+}
+
+/**
+ * @brief Read chip status register.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] stat_cmd: Read status command.
+ * @return Chip status.
+ */
+__attribute__((always_inline)) static inline uint8_t
+read_status(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd)
+{
+ wait_tx_finish(sr);
+ flush_rx(sr, dr);
+ /*
+ * Don't bother with wait_tx_available() as TX FIFO is empty
+ * and we only send two bytes.
+ */
+ _send_byte(dr, stat_cmd);
+ _send_byte(dr, 0); // Dummy write to push out read data.
+ wait_rx_available(sr);
+ rcv_byte(dr); // Dummy read to skip command byte.
+ wait_rx_available(sr);
+ return rcv_byte(dr);
+}
+
+/**
+ * @brief Enable Flash chip write.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] we_cmd: Write enable command.
+ */
+__attribute__((always_inline)) static inline void
+write_enable(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t we_cmd)
+{
+ wait_tx_finish(sr);
+ _send_byte(dr, we_cmd);
+}
+
+/**
+ * @brief Erase Flash sector.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] erase_cmd: Erase sector cmd.
+ * @param[in] address: Sector address.
+ * @param[in] four_byte_mode: Device is in 32 bit mode flag.
+ */
+__attribute__((always_inline)) static inline void
+erase_sector(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t erase_cmd,
+ uint32_t address, uint8_t four_byte_mode)
+{
+ wait_tx_finish(sr);
+ _send_byte(dr, erase_cmd);
+ if (four_byte_mode)
+ send_u32(sr, dr, address);
+ else
+ send_u24(sr, dr, address);
+}
+
+/**
+ * @brief Wait for write enable flag.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] stat_cmd: Read status command.
+ * @param[in] we_mask: Write enable status mask.
+ */
+__attribute__((always_inline)) static inline void
+wait_write_enable(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd,
+ uint8_t we_mask)
+{
+ while (!(read_status(sr, dr, stat_cmd) & we_mask))
+ ;
+}
+
+/**
+ * @brief Wait while flash is busy.
+ *
+ * @param[in] sr: Pointer to SR register.
+ * @param[in] dr: Pointer to DR register.
+ * @param[in] stat_cmd: Read status command.
+ * @param[in] busy_mask: Flash busy mask.
+ */
+__attribute__((always_inline)) static inline void
+wait_busy(volatile uint8_t *sr, volatile uint8_t *dr, uint8_t stat_cmd,
+ uint8_t busy_mask)
+{
+ while (read_status(sr, dr, stat_cmd) & busy_mask)
+ ;
+}
+
+#endif // _DW_SPI_H_
diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc
new file mode 100644
index 0000000..94c732f
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc
@@ -0,0 +1,39 @@
+ 0x0b, 0x00, 0x82, 0x88, 0x1f, 0x00, 0x8a, 0x88, 0x0f, 0x00, 0x83, 0x88,
+ 0x17, 0x00, 0x86, 0x88, 0x08, 0x00, 0x82, 0x98, 0x1c, 0x00, 0x8a, 0x98,
+ 0x0c, 0x00, 0x83, 0x98, 0x14, 0x00, 0x86, 0x98, 0x25, 0x38, 0x80, 0x00,
+ 0x54, 0x00, 0x40, 0x10, 0xf8, 0xff, 0x09, 0x24, 0x00, 0x00, 0x64, 0x90,
+ 0x05, 0x00, 0x84, 0x30, 0x04, 0x00, 0x84, 0x38, 0xfc, 0xff, 0x80, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30,
+ 0x07, 0x00, 0x40, 0x50, 0x25, 0x00, 0xe5, 0x90, 0x00, 0x00, 0xc2, 0x90,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0xe5, 0x90, 0x00, 0x00, 0x62, 0x90,
+ 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc5, 0xa0, 0x26, 0x00, 0xe2, 0x90, 0x45, 0x00, 0x40, 0x10,
+ 0x03, 0x00, 0xe8, 0x88, 0x00, 0x00, 0xe8, 0x98, 0x18, 0x00, 0x05, 0x24,
+ 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10,
+ 0x06, 0x10, 0xa8, 0x00, 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xa5, 0x24,
+ 0x00, 0x00, 0xc2, 0xa0, 0xf8, 0xff, 0xa9, 0x14, 0x05, 0x00, 0x0b, 0x24,
+ 0x07, 0x00, 0xe8, 0x88, 0x04, 0x00, 0xe8, 0x98, 0x1e, 0x00, 0x00, 0x11,
+ 0x25, 0x28, 0x00, 0x01, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30,
+ 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa0,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x06, 0x00, 0x40, 0x50,
+ 0xff, 0xff, 0xa5, 0x24, 0x00, 0x00, 0xc2, 0x90, 0x25, 0x00, 0x60, 0x51,
+ 0x24, 0x00, 0xec, 0x90, 0xff, 0xff, 0x6b, 0x25, 0xff, 0xff, 0xa5, 0x24,
+ 0xf1, 0xff, 0xa0, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x51,
+ 0x01, 0x00, 0x04, 0x24, 0x24, 0x00, 0xe5, 0x90, 0x00, 0x00, 0x62, 0x90,
+ 0x08, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc2, 0x90, 0xff, 0x00, 0x42, 0x30, 0x04, 0x00, 0xa2, 0x14,
+ 0xff, 0xff, 0x08, 0x25, 0xf7, 0xff, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x04, 0x24, 0x00, 0x00, 0x44, 0xa1, 0x0b, 0x00, 0xe2, 0x88,
+ 0x01, 0x00, 0x4a, 0x25, 0x08, 0x00, 0xe2, 0x98, 0xff, 0xff, 0x42, 0x24,
+ 0x0b, 0x00, 0xe2, 0xa8, 0x08, 0x00, 0xe2, 0xb8, 0x03, 0x00, 0xe4, 0x88,
+ 0x07, 0x00, 0xe5, 0x88, 0x00, 0x00, 0xe4, 0x98, 0x04, 0x00, 0xe5, 0x98,
+ 0x21, 0x20, 0x85, 0x00, 0x03, 0x00, 0xe4, 0xa8, 0xae, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0xe4, 0xb8, 0x3f, 0x00, 0x00, 0x70, 0x08, 0x00, 0xe0, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x42, 0x30, 0xed, 0xff, 0x82, 0x55,
+ 0x00, 0x00, 0x44, 0xa1, 0xd9, 0xff, 0x00, 0x10, 0xff, 0xff, 0x08, 0x25,
+ 0x00, 0x00, 0xe8, 0x98, 0x10, 0x00, 0x05, 0x24, 0x00, 0x00, 0x62, 0x90,
+ 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x06, 0x10, 0xa8, 0x00,
+ 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xa5, 0x24, 0x00, 0x00, 0xc2, 0xa0,
+ 0xf8, 0xff, 0xa9, 0x14, 0x04, 0x00, 0x0b, 0x24, 0xbc, 0xff, 0x00, 0x10,
+ 0x07, 0x00, 0xe8, 0x88
diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc
new file mode 100644
index 0000000..b72c7ea
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc
@@ -0,0 +1,39 @@
+ 0x0b, 0x00, 0x88, 0x88, 0x25, 0x28, 0x80, 0x00, 0x03, 0x00, 0x86, 0x88,
+ 0x0f, 0x00, 0x82, 0x88, 0x17, 0x00, 0x84, 0x88, 0x08, 0x00, 0xa8, 0x98,
+ 0x00, 0x00, 0xa6, 0x98, 0x0c, 0x00, 0xa2, 0x98, 0x5f, 0x00, 0x00, 0x11,
+ 0x14, 0x00, 0xa4, 0x98, 0xf8, 0xff, 0x07, 0x24, 0x1d, 0x00, 0xa9, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38,
+ 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0,
+ 0x1c, 0x00, 0xaa, 0x90, 0x1f, 0x00, 0xa9, 0x90, 0x00, 0x00, 0x43, 0x90,
+ 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30,
+ 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90,
+ 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xaa, 0x90, 0x21, 0x00, 0xa9, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38,
+ 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0,
+ 0x31, 0x00, 0x20, 0x11, 0x10, 0x00, 0x09, 0x24, 0x18, 0x00, 0x09, 0x24,
+ 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10,
+ 0x06, 0x18, 0x26, 0x01, 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25,
+ 0xf9, 0xff, 0x27, 0x15, 0x00, 0x00, 0x83, 0xa0, 0x1c, 0x00, 0xaa, 0x90,
+ 0x20, 0x00, 0xa9, 0x90, 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30,
+ 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0x06, 0x00, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90,
+ 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x43, 0x90,
+ 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30,
+ 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90,
+ 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0xa3, 0x88, 0xff, 0xff, 0x08, 0x25, 0x04, 0x00, 0xa3, 0x98,
+ 0xa4, 0xff, 0x00, 0x15, 0x21, 0x30, 0xc3, 0x00, 0x3f, 0x00, 0x00, 0x70,
+ 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90,
+ 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x06, 0x18, 0x26, 0x01,
+ 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, 0xf9, 0xff, 0x27, 0x15,
+ 0x00, 0x00, 0x83, 0xa0, 0xd1, 0xff, 0x00, 0x10, 0x1c, 0x00, 0xaa, 0x90
diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc
new file mode 100644
index 0000000..31500e0
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc
@@ -0,0 +1,51 @@
+ 0x13, 0x00, 0x88, 0x88, 0x25, 0x30, 0x80, 0x00, 0x0b, 0x00, 0x85, 0x88,
+ 0x17, 0x00, 0x82, 0x88, 0x1f, 0x00, 0x84, 0x88, 0x10, 0x00, 0xc8, 0x98,
+ 0x08, 0x00, 0xc5, 0x98, 0x14, 0x00, 0xc2, 0x98, 0x1c, 0x00, 0xc4, 0x98,
+ 0x78, 0x00, 0x00, 0x11, 0xf8, 0xff, 0x07, 0x24, 0x25, 0x00, 0xc9, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38,
+ 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0,
+ 0x24, 0x00, 0xca, 0x90, 0x27, 0x00, 0xc9, 0x90, 0x00, 0x00, 0x43, 0x90,
+ 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30,
+ 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfc, 0xff, 0x60, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0, 0x00, 0x00, 0x80, 0xa0,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90,
+ 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01, 0xe4, 0xff, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30,
+ 0x04, 0x00, 0x63, 0x38, 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x00, 0xc9, 0x90, 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30,
+ 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0,
+ 0x29, 0x00, 0xc3, 0x90, 0x47, 0x00, 0x60, 0x10, 0x03, 0x00, 0xca, 0x88,
+ 0x00, 0x00, 0xca, 0x98, 0x18, 0x00, 0x09, 0x24, 0x00, 0x00, 0x43, 0x90,
+ 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10, 0x06, 0x18, 0x2a, 0x01,
+ 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25, 0x00, 0x00, 0x83, 0xa0,
+ 0xf8, 0xff, 0x27, 0x15, 0x25, 0x58, 0x00, 0x01, 0x07, 0x00, 0xc3, 0x88,
+ 0x04, 0x00, 0xc3, 0x98, 0x2b, 0x48, 0x03, 0x01, 0x0a, 0x58, 0x69, 0x00,
+ 0x0d, 0x00, 0x60, 0x11, 0x21, 0x50, 0xab, 0x00, 0x00, 0x00, 0xa9, 0x90,
+ 0x01, 0x00, 0xa5, 0x24, 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30,
+ 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xa0,
+ 0xf9, 0xff, 0xaa, 0x54, 0x00, 0x00, 0xa9, 0x90, 0x07, 0x00, 0xc3, 0x88,
+ 0x23, 0x40, 0x0b, 0x01, 0x04, 0x00, 0xc3, 0x98, 0x03, 0x00, 0xc9, 0x88,
+ 0x00, 0x00, 0xc9, 0x98, 0x21, 0x18, 0x23, 0x01, 0x03, 0x00, 0xc3, 0xa8,
+ 0x00, 0x00, 0xc3, 0xb8, 0x24, 0x00, 0xca, 0x90, 0x28, 0x00, 0xc9, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x05, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x38,
+ 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90,
+ 0x08, 0x00, 0x63, 0x30, 0x06, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30,
+ 0xfc, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xa0,
+ 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30,
+ 0xfd, 0xff, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90,
+ 0x00, 0x00, 0x43, 0x90, 0x08, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x90, 0x24, 0x18, 0x23, 0x01,
+ 0xe4, 0xff, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xff, 0x00, 0x55,
+ 0x25, 0x00, 0xc9, 0x90, 0x3f, 0x00, 0x00, 0x70, 0x08, 0x00, 0xe0, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x98, 0x10, 0x00, 0x09, 0x24,
+ 0x00, 0x00, 0x43, 0x90, 0x02, 0x00, 0x63, 0x30, 0xfd, 0xff, 0x60, 0x10,
+ 0x06, 0x18, 0x2a, 0x01, 0xff, 0x00, 0x63, 0x30, 0xf8, 0xff, 0x29, 0x25,
+ 0x00, 0x00, 0x83, 0xa0, 0xf8, 0xff, 0x27, 0x15, 0x25, 0x58, 0x00, 0x01,
+ 0x07, 0x00, 0xc3, 0x88, 0x04, 0x00, 0xc3, 0x98, 0x2b, 0x48, 0x03, 0x01,
+ 0x0a, 0x58, 0x69, 0x00, 0xbb, 0xff, 0x60, 0x15, 0x21, 0x50, 0xab, 0x00,
+ 0xc6, 0xff, 0x00, 0x10, 0x03, 0x00, 0xc9, 0x88
diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc
new file mode 100644
index 0000000..3f18b7c
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc
@@ -0,0 +1,33 @@
+ 0x0f, 0x00, 0x87, 0x88, 0x07, 0x00, 0x88, 0x88, 0x13, 0x00, 0x83, 0x88,
+ 0x1b, 0x00, 0x85, 0x88, 0x0c, 0x00, 0x87, 0x98, 0x04, 0x00, 0x88, 0x98,
+ 0x10, 0x00, 0x83, 0x98, 0x18, 0x00, 0x85, 0x98, 0x00, 0x00, 0x62, 0x90,
+ 0x05, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x38, 0xfc, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30,
+ 0x07, 0x00, 0x40, 0x50, 0x20, 0x00, 0x86, 0x90, 0x00, 0x00, 0xa2, 0x90,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x86, 0x90, 0x00, 0x00, 0x62, 0x90,
+ 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa6, 0xa0, 0x21, 0x00, 0x82, 0x90, 0x35, 0x00, 0x40, 0x10,
+ 0x03, 0x00, 0x82, 0x88, 0x18, 0x00, 0x06, 0x24, 0xf8, 0xff, 0x09, 0x24,
+ 0x00, 0x00, 0x82, 0x98, 0x25, 0x20, 0x40, 0x00, 0x00, 0x00, 0x62, 0x90,
+ 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10, 0x06, 0x10, 0xc4, 0x00,
+ 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xc6, 0x24, 0xf9, 0xff, 0xc9, 0x14,
+ 0x00, 0x00, 0xa2, 0xa0, 0x05, 0x00, 0x06, 0x24, 0x23, 0x00, 0xe0, 0x10,
+ 0x25, 0x20, 0xe0, 0x00, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30,
+ 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xa0,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x06, 0x00, 0x40, 0x50,
+ 0xff, 0xff, 0x84, 0x24, 0x00, 0x00, 0xa2, 0x90, 0x14, 0x00, 0xc0, 0x50,
+ 0x00, 0x00, 0x02, 0xa1, 0xff, 0xff, 0xc6, 0x24, 0xff, 0xff, 0x84, 0x24,
+ 0xf1, 0xff, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0xe0, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30,
+ 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x90,
+ 0x03, 0x00, 0xc0, 0x50, 0xff, 0xff, 0xe7, 0x24, 0xf8, 0xff, 0x00, 0x10,
+ 0xff, 0xff, 0xc6, 0x24, 0x06, 0x00, 0xe0, 0x10, 0x00, 0x00, 0x02, 0xa1,
+ 0xf4, 0xff, 0x00, 0x10, 0x01, 0x00, 0x08, 0x25, 0xff, 0xff, 0xe7, 0x24,
+ 0xec, 0xff, 0x00, 0x10, 0x01, 0x00, 0x08, 0x25, 0x3f, 0x00, 0x00, 0x70,
+ 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x24,
+ 0xf8, 0xff, 0x09, 0x24, 0x00, 0x00, 0x82, 0x98, 0x25, 0x20, 0x40, 0x00,
+ 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10,
+ 0x06, 0x10, 0xc4, 0x00, 0xff, 0x00, 0x42, 0x30, 0xf8, 0xff, 0xc6, 0x24,
+ 0xf9, 0xff, 0xc9, 0x14, 0x00, 0x00, 0xa2, 0xa0, 0xcc, 0xff, 0x00, 0x10,
+ 0x04, 0x00, 0x06, 0x24
diff --git a/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc
new file mode 100644
index 0000000..384dbad
--- /dev/null
+++ b/contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc
@@ -0,0 +1,21 @@
+ 0x03, 0x00, 0x85, 0x88, 0x0b, 0x00, 0x88, 0x88, 0x0f, 0x00, 0x83, 0x88,
+ 0x17, 0x00, 0x86, 0x88, 0x00, 0x00, 0x85, 0x98, 0x08, 0x00, 0x88, 0x98,
+ 0x0c, 0x00, 0x83, 0x98, 0x14, 0x00, 0x86, 0x98, 0x00, 0x00, 0x62, 0x90,
+ 0x05, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x38, 0xfc, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30,
+ 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfc, 0xff, 0x40, 0x14,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x25, 0x38, 0xa0, 0x00, 0x21, 0x40, 0x05, 0x01, 0x00, 0x00, 0xa9, 0x90,
+ 0x01, 0x00, 0xa5, 0x24, 0x00, 0x00, 0x62, 0x90, 0x02, 0x00, 0x42, 0x30,
+ 0xfd, 0xff, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xa0,
+ 0x1c, 0x00, 0x82, 0x90, 0x08, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0x04, 0x00, 0x40, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90, 0x01, 0x00, 0xe7, 0x24,
+ 0xff, 0xff, 0xe2, 0xa0, 0xef, 0xff, 0xa8, 0x54, 0x00, 0x00, 0xa9, 0x90,
+ 0x1c, 0x00, 0x82, 0x90, 0x0c, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x10, 0xe8, 0x00, 0x09, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x90, 0x08, 0x00, 0x42, 0x30, 0xfd, 0xff, 0x40, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x90, 0x01, 0x00, 0xe7, 0x24,
+ 0xf9, 0xff, 0x07, 0x15, 0xff, 0xff, 0xe2, 0xa0, 0x3f, 0x00, 0x00, 0x70,
+ 0x08, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00