aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorthead_admin <occ_thead@service.alibaba.com>2022-09-13 11:04:33 +0800
committerthead_admin <occ_thead@service.alibaba.com>2022-09-13 11:04:33 +0800
commit43db9e00d5837c100c0b2fbbee64a08ab807d1e0 (patch)
treeb40c0eed02935b6682e8c5c975e3016b6b2f55fe /lib
Linux_SDK_V0.9.5Linux_SDK_V0.9.5
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig594
-rw-r--r--lib/Makefile140
-rw-r--r--lib/addr_map.c71
-rw-r--r--lib/aes.c657
-rw-r--r--lib/asm-offsets.c43
-rw-r--r--lib/asn1_decoder.c527
-rw-r--r--lib/at91/Makefile6
-rw-r--r--lib/at91/at91.c29
-rw-r--r--lib/at91/atmel_logo_8bpp.h1309
-rw-r--r--lib/at91/microchip_logo_8bpp.h1081
-rw-r--r--lib/bch.c1407
-rw-r--r--lib/bitrev.c48
-rw-r--r--lib/bzip2/Makefile5
-rw-r--r--lib/bzip2/bzlib.c1601
-rw-r--r--lib/bzip2/bzlib_blocksort.c1134
-rw-r--r--lib/bzip2/bzlib_compress.c713
-rw-r--r--lib/bzip2/bzlib_crctable.c145
-rw-r--r--lib/bzip2/bzlib_decompress.c674
-rw-r--r--lib/bzip2/bzlib_huffman.c229
-rw-r--r--lib/bzip2/bzlib_private.h530
-rw-r--r--lib/bzip2/bzlib_randtable.c125
-rw-r--r--lib/charset.c462
-rw-r--r--lib/circbuf.c100
-rw-r--r--lib/crc16.c84
-rw-r--r--lib/crc32.c267
-rw-r--r--lib/crc32c.c38
-rw-r--r--lib/crc7.c62
-rw-r--r--lib/crc8.c36
-rw-r--r--lib/crypto/Kconfig52
-rw-r--r--lib/crypto/Makefile49
-rw-r--r--lib/crypto/asymmetric_type.c668
-rw-r--r--lib/crypto/pkcs7.asn1135
-rw-r--r--lib/crypto/pkcs7_parser.c693
-rw-r--r--lib/crypto/pkcs7_parser.h65
-rw-r--r--lib/crypto/public_key.c376
-rw-r--r--lib/crypto/rsa_helper.c198
-rw-r--r--lib/crypto/rsapubkey.asn14
-rw-r--r--lib/crypto/x509.asn160
-rw-r--r--lib/crypto/x509_akid.asn135
-rw-r--r--lib/crypto/x509_cert_parser.c697
-rw-r--r--lib/crypto/x509_parser.h57
-rw-r--r--lib/crypto/x509_public_key.c292
-rw-r--r--lib/ctype.c39
-rw-r--r--lib/date.c119
-rw-r--r--lib/dhry/Kconfig7
-rw-r--r--lib/dhry/Makefile5
-rw-r--r--lib/dhry/cmd_dhry.c35
-rw-r--r--lib/dhry/dhry.h441
-rw-r--r--lib/dhry/dhry_1.c420
-rw-r--r--lib/dhry/dhry_2.c216
-rw-r--r--lib/display_options.c215
-rw-r--r--lib/div64.c191
-rw-r--r--lib/efi/Kconfig54
-rw-r--r--lib/efi/Makefile17
-rw-r--r--lib/efi/efi.c98
-rw-r--r--lib/efi/efi_app.c164
-rw-r--r--lib/efi/efi_info.c46
-rw-r--r--lib/efi/efi_stub.c390
-rw-r--r--lib/efi_driver/Makefile11
-rw-r--r--lib/efi_driver/efi_block_device.c210
-rw-r--r--lib/efi_driver/efi_uclass.c347
-rw-r--r--lib/efi_loader/.gitignore2
-rw-r--r--lib/efi_loader/Kconfig123
-rw-r--r--lib/efi_loader/Makefile44
-rw-r--r--lib/efi_loader/efi_acpi.c42
-rw-r--r--lib/efi_loader/efi_bootmgr.c282
-rw-r--r--lib/efi_loader/efi_boottime.c3678
-rw-r--r--lib/efi_loader/efi_console.c1158
-rw-r--r--lib/efi_loader/efi_device_path.c1076
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c369
-rw-r--r--lib/efi_loader/efi_device_path_utilities.c199
-rw-r--r--lib/efi_loader/efi_disk.c516
-rw-r--r--lib/efi_loader/efi_file.c883
-rw-r--r--lib/efi_loader/efi_freestanding.c90
-rw-r--r--lib/efi_loader/efi_gop.c530
-rw-r--r--lib/efi_loader/efi_hii.c1073
-rw-r--r--lib/efi_loader/efi_hii_config.c146
-rw-r--r--lib/efi_loader/efi_image_loader.c344
-rw-r--r--lib/efi_loader/efi_memory.c788
-rw-r--r--lib/efi_loader/efi_net.c946
-rw-r--r--lib/efi_loader/efi_root_node.c87
-rw-r--r--lib/efi_loader/efi_runtime.c883
-rw-r--r--lib/efi_loader/efi_setup.c185
-rw-r--r--lib/efi_loader/efi_smbios.c55
-rw-r--r--lib/efi_loader/efi_unicode_collation.c368
-rw-r--r--lib/efi_loader/efi_variable.c643
-rw-r--r--lib/efi_loader/efi_watchdog.c88
-rw-r--r--lib/efi_loader/helloworld.c94
-rw-r--r--lib/efi_selftest/.gitignore4
-rw-r--r--lib/efi_selftest/Kconfig9
-rw-r--r--lib/efi_selftest/Makefile98
-rw-r--r--lib/efi_selftest/efi_freestanding.c11
-rw-r--r--lib/efi_selftest/efi_selftest.c318
-rw-r--r--lib/efi_selftest/efi_selftest_bitblt.c310
-rw-r--r--lib/efi_selftest/efi_selftest_block_device.c512
-rw-r--r--lib/efi_selftest/efi_selftest_config_table.c267
-rw-r--r--lib/efi_selftest/efi_selftest_console.c255
-rw-r--r--lib/efi_selftest/efi_selftest_controllers.c415
-rw-r--r--lib/efi_selftest/efi_selftest_crc32.c142
-rw-r--r--lib/efi_selftest/efi_selftest_devicepath.c402
-rw-r--r--lib/efi_selftest/efi_selftest_devicepath_util.c280
-rw-r--r--lib/efi_selftest/efi_selftest_disk_image.h54
-rw-r--r--lib/efi_selftest/efi_selftest_event_groups.c138
-rw-r--r--lib/efi_selftest/efi_selftest_events.c204
-rw-r--r--lib/efi_selftest/efi_selftest_exception.c147
-rw-r--r--lib/efi_selftest/efi_selftest_exitbootservices.c88
-rw-r--r--lib/efi_selftest/efi_selftest_fdt.c206
-rw-r--r--lib/efi_selftest/efi_selftest_gop.c99
-rw-r--r--lib/efi_selftest/efi_selftest_hii.c1060
-rw-r--r--lib/efi_selftest/efi_selftest_hii_data.c453
-rw-r--r--lib/efi_selftest/efi_selftest_loaded_image.c107
-rw-r--r--lib/efi_selftest/efi_selftest_loadimage.c528
-rw-r--r--lib/efi_selftest/efi_selftest_manageprotocols.c382
-rw-r--r--lib/efi_selftest/efi_selftest_memory.c192
-rw-r--r--lib/efi_selftest/efi_selftest_miniapp_exception.c41
-rw-r--r--lib/efi_selftest/efi_selftest_miniapp_exit.c91
-rw-r--r--lib/efi_selftest/efi_selftest_miniapp_return.c31
-rw-r--r--lib/efi_selftest/efi_selftest_open_protocol.c205
-rw-r--r--lib/efi_selftest/efi_selftest_register_notify.c236
-rw-r--r--lib/efi_selftest/efi_selftest_rtc.c102
-rw-r--r--lib/efi_selftest/efi_selftest_set_virtual_address_map.c207
-rw-r--r--lib/efi_selftest/efi_selftest_snp.c485
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_exit.c161
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_return.c148
-rw-r--r--lib/efi_selftest/efi_selftest_textinput.c97
-rw-r--r--lib/efi_selftest/efi_selftest_textinputex.c198
-rw-r--r--lib/efi_selftest/efi_selftest_textoutput.c130
-rw-r--r--lib/efi_selftest/efi_selftest_tpl.c226
-rw-r--r--lib/efi_selftest/efi_selftest_unaligned.c66
-rw-r--r--lib/efi_selftest/efi_selftest_unicode_collation.c260
-rw-r--r--lib/efi_selftest/efi_selftest_util.c112
-rw-r--r--lib/efi_selftest/efi_selftest_variables.c206
-rw-r--r--lib/efi_selftest/efi_selftest_variables_runtime.c94
-rw-r--r--lib/efi_selftest/efi_selftest_watchdog.c230
-rw-r--r--lib/errno.c1
-rw-r--r--lib/errno_str.c153
-rw-r--r--lib/fdtdec.c1668
-rw-r--r--lib/fdtdec_common.c55
-rw-r--r--lib/fdtdec_test.c350
-rw-r--r--lib/gunzip.c309
-rw-r--r--lib/gzip.c127
-rw-r--r--lib/hang.c34
-rw-r--r--lib/hashtable.c996
-rw-r--r--lib/hexdump.c245
-rw-r--r--lib/image-sparse.c261
-rw-r--r--lib/ldiv.c42
-rw-r--r--lib/libavb/Makefile13
-rw-r--r--lib/libavb/avb_chain_partition_descriptor.c45
-rw-r--r--lib/libavb/avb_chain_partition_descriptor.h53
-rw-r--r--lib/libavb/avb_cmdline.c459
-rw-r--r--lib/libavb/avb_cmdline.h73
-rw-r--r--lib/libavb/avb_crypto.c353
-rw-r--r--lib/libavb/avb_crypto.h155
-rw-r--r--lib/libavb/avb_descriptor.c148
-rw-r--r--lib/libavb/avb_descriptor.h112
-rw-r--r--lib/libavb/avb_footer.c35
-rw-r--r--lib/libavb/avb_footer.h67
-rw-r--r--lib/libavb/avb_hash_descriptor.c43
-rw-r--r--lib/libavb/avb_hash_descriptor.h69
-rw-r--r--lib/libavb/avb_hashtree_descriptor.c51
-rw-r--r--lib/libavb/avb_hashtree_descriptor.h79
-rw-r--r--lib/libavb/avb_kernel_cmdline_descriptor.c39
-rw-r--r--lib/libavb/avb_kernel_cmdline_descriptor.h62
-rw-r--r--lib/libavb/avb_ops.h321
-rw-r--r--lib/libavb/avb_property_descriptor.c166
-rw-r--r--lib/libavb/avb_property_descriptor.h88
-rw-r--r--lib/libavb/avb_rsa.c275
-rw-r--r--lib/libavb/avb_rsa.h54
-rw-r--r--lib/libavb/avb_sha.h71
-rw-r--r--lib/libavb/avb_sha256.c375
-rw-r--r--lib/libavb/avb_sha512.c361
-rw-r--r--lib/libavb/avb_slot_verify.c1724
-rw-r--r--lib/libavb/avb_slot_verify.h381
-rw-r--r--lib/libavb/avb_sysdeps.h108
-rw-r--r--lib/libavb/avb_sysdeps_posix.c66
-rw-r--r--lib/libavb/avb_util.c411
-rw-r--r--lib/libavb/avb_util.h268
-rw-r--r--lib/libavb/avb_vbmeta_image.c290
-rw-r--r--lib/libavb/avb_vbmeta_image.h275
-rw-r--r--lib/libavb/avb_version.c15
-rw-r--r--lib/libavb/avb_version.h40
-rw-r--r--lib/libavb/libavb.h31
-rw-r--r--lib/libfdt/Makefile26
-rw-r--r--lib/libfdt/README25
-rw-r--r--lib/libfdt/fdt.c2
-rw-r--r--lib/libfdt/fdt_addresses.c2
-rw-r--r--lib/libfdt/fdt_empty_tree.c2
-rw-r--r--lib/libfdt/fdt_overlay.c2
-rw-r--r--lib/libfdt/fdt_region.c656
-rw-r--r--lib/libfdt/fdt_ro.c925
-rw-r--r--lib/libfdt/fdt_rw.c2
-rw-r--r--lib/libfdt/fdt_strerror.c2
-rw-r--r--lib/libfdt/fdt_sw.c2
-rw-r--r--lib/libfdt/fdt_wip.c2
-rw-r--r--lib/libfdt/libfdt_internal.h1
-rw-r--r--lib/libfdt/test_libfdt.py14
-rw-r--r--lib/linux_compat.c61
-rw-r--r--lib/linux_string.c51
-rw-r--r--lib/list_sort.c297
-rw-r--r--lib/lmb.c428
-rw-r--r--lib/lz4.c242
-rw-r--r--lib/lz4_wrapper.c138
-rw-r--r--lib/lzma/LzmaDec.c1025
-rw-r--r--lib/lzma/LzmaDec.h223
-rw-r--r--lib/lzma/LzmaTools.c123
-rw-r--r--lib/lzma/LzmaTools.h18
-rw-r--r--lib/lzma/Makefile11
-rw-r--r--lib/lzma/README.txt28
-rw-r--r--lib/lzma/Types.h234
-rw-r--r--lib/lzma/history.txt271
-rw-r--r--lib/lzma/import_lzmasdk.sh36
-rw-r--r--lib/lzma/license.txt3
-rw-r--r--lib/lzma/lzma.txt598
-rw-r--r--lib/lzo/Makefile6
-rw-r--r--lib/lzo/lzo1x_decompress.c359
-rw-r--r--lib/lzo/lzodefs.h43
-rw-r--r--lib/md5.c314
-rw-r--r--lib/membuff.c389
-rw-r--r--lib/net_utils.c58
-rw-r--r--lib/of_live.c335
-rw-r--r--lib/oid_registry.c179
-rw-r--r--lib/optee/Kconfig41
-rw-r--r--lib/optee/Makefile5
-rw-r--r--lib/optee/optee.c205
-rw-r--r--lib/panic.c55
-rw-r--r--lib/physmem.c24
-rw-r--r--lib/qsort.c72
-rw-r--r--lib/rand.c32
-rw-r--r--lib/rbtree.c550
-rw-r--r--lib/rc4.c48
-rw-r--r--lib/rsa/Kconfig37
-rw-r--r--lib/rsa/Makefile9
-rw-r--r--lib/rsa/rsa-checksum.c51
-rw-r--r--lib/rsa/rsa-mod-exp.c353
-rw-r--r--lib/rsa/rsa-sign.c832
-rw-r--r--lib/rsa/rsa-verify.c463
-rw-r--r--lib/sec_library/include/aes.h265
-rw-r--r--lib/sec_library/include/csi_efuse_api.h56
-rw-r--r--lib/sec_library/include/csi_sec_img_verify.h31
-rw-r--r--lib/sec_library/include/kdf.h142
-rw-r--r--lib/sec_library/include/keyram.h78
-rw-r--r--lib/sec_library/include/rng.h40
-rw-r--r--lib/sec_library/include/rsa.h264
-rwxr-xr-xlib/sec_library/include/sec_crypto_aes.h263
-rw-r--r--lib/sec_library/include/sec_crypto_common.h27
-rwxr-xr-xlib/sec_library/include/sec_crypto_errcode.h92
-rwxr-xr-xlib/sec_library/include/sec_crypto_rng.h41
-rwxr-xr-xlib/sec_library/include/sec_crypto_rsa.h293
-rwxr-xr-xlib/sec_library/include/sec_crypto_sha.h173
-rwxr-xr-xlib/sec_library/include/sec_crypto_sm2.h242
-rwxr-xr-xlib/sec_library/include/sec_crypto_sm4.h236
-rwxr-xr-xlib/sec_library/include/sec_library.h15
-rw-r--r--lib/sec_library/include/sha.h160
-rw-r--r--lib/sec_library/include/sm2.h258
-rw-r--r--lib/sec_library/include/sm3.h155
-rw-r--r--lib/sec_library/include/sm4.h249
-rw-r--r--lib/sec_library/libsec_library.abin0 -> 6645534 bytes
-rw-r--r--lib/sha1.c445
-rw-r--r--lib/sha256.c291
-rw-r--r--lib/slre.c722
-rw-r--r--lib/smbios.c338
-rw-r--r--lib/string.c729
-rw-r--r--lib/strto.c165
-rw-r--r--lib/tables_csum.c19
-rw-r--r--lib/time.c187
-rw-r--r--lib/tiny-printf.c417
-rw-r--r--lib/tizen/Makefile6
-rw-r--r--lib/tizen/tizen.c34
-rw-r--r--lib/tizen/tizen_logo_16bpp.h7934
-rw-r--r--lib/tizen/tizen_logo_16bpp_gzip.h647
-rw-r--r--lib/tpm-common.c198
-rw-r--r--lib/tpm-utils.h84
-rw-r--r--lib/tpm-v1.c920
-rw-r--r--lib/tpm-v2.c423
-rw-r--r--lib/trace.c421
-rw-r--r--lib/uuid.c326
-rw-r--r--lib/vsprintf.c890
-rw-r--r--lib/xxhash.c467
-rw-r--r--lib/zlib/Makefile6
-rw-r--r--lib/zlib/adler32.c122
-rw-r--r--lib/zlib/deflate.c1833
-rw-r--r--lib/zlib/deflate.h342
-rw-r--r--lib/zlib/inffast.c356
-rw-r--r--lib/zlib/inffast.h11
-rw-r--r--lib/zlib/inffixed.h94
-rw-r--r--lib/zlib/inflate.c943
-rw-r--r--lib/zlib/inflate.h115
-rw-r--r--lib/zlib/inftrees.c325
-rw-r--r--lib/zlib/inftrees.h55
-rw-r--r--lib/zlib/trees.c1244
-rw-r--r--lib/zlib/trees.h127
-rw-r--r--lib/zlib/zlib.c32
-rw-r--r--lib/zlib/zlib.h20
-rw-r--r--lib/zlib/zutil.c71
-rw-r--r--lib/zlib/zutil.h126
-rw-r--r--lib/zstd/Makefile4
-rw-r--r--lib/zstd/bitstream.h344
-rw-r--r--lib/zstd/decompress.c2515
-rw-r--r--lib/zstd/entropy_common.c213
-rw-r--r--lib/zstd/error_private.h43
-rw-r--r--lib/zstd/fse.h545
-rw-r--r--lib/zstd/fse_decompress.c302
-rw-r--r--lib/zstd/huf.h182
-rw-r--r--lib/zstd/huf_decompress.c930
-rw-r--r--lib/zstd/mem.h142
-rw-r--r--lib/zstd/zstd_common.c65
-rw-r--r--lib/zstd/zstd_internal.h253
-rw-r--r--lib/zstd/zstd_opt.h1004
308 files changed, 95656 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
new file mode 100644
index 00000000..965cf7bc
--- /dev/null
+++ b/lib/Kconfig
@@ -0,0 +1,594 @@
+menu "Library routines"
+
+config BCH
+ bool "Enable Software based BCH ECC"
+ help
+ Enables software based BCH ECC algorithm present in lib/bch.c
+ This is used by SoC platforms which do not have built-in ELM
+ hardware engine required for BCH ECC correction.
+
+config CC_OPTIMIZE_LIBS_FOR_SPEED
+ bool "Optimize libraries for speed"
+ help
+ Enabling this option will pass "-O2" to gcc when compiling
+ under "lib" directory.
+
+ If unsure, say N.
+
+config DYNAMIC_CRC_TABLE
+ bool "Enable Dynamic tables for CRC"
+ help
+ Enable this option to calculate entries for CRC tables at runtime.
+ This can be helpful when reducing the size of the build image
+
+config HAVE_ARCH_IOMAP
+ bool
+ help
+ Enable this option if architecture provides io{read,write}{8,16,32}
+ I/O accessor functions.
+
+config HAVE_PRIVATE_LIBGCC
+ bool
+
+config LIB_UUID
+ bool
+
+config PRINTF
+ bool
+ default y
+
+config SPL_PRINTF
+ bool
+ select SPL_SPRINTF
+ select SPL_STRTO if !SPL_USE_TINY_PRINTF
+
+config TPL_PRINTF
+ bool
+ select TPL_SPRINTF
+ select TPL_STRTO if !TPL_USE_TINY_PRINTF
+
+config SPRINTF
+ bool
+ default y
+
+config SPL_SPRINTF
+ bool
+
+config TPL_SPRINTF
+ bool
+
+config STRTO
+ bool
+ default y
+
+config SPL_STRTO
+ bool
+
+config TPL_STRTO
+ bool
+
+config IMAGE_SPARSE
+ bool
+
+config IMAGE_SPARSE_FILLBUF_SIZE
+ hex "Android sparse image CHUNK_TYPE_FILL buffer size"
+ default 0x80000
+ depends on IMAGE_SPARSE
+ help
+ Set the size of the fill buffer used when processing CHUNK_TYPE_FILL
+ chunks.
+
+config USE_PRIVATE_LIBGCC
+ bool "Use private libgcc"
+ depends on HAVE_PRIVATE_LIBGCC
+ default y if HAVE_PRIVATE_LIBGCC && ((ARM && !ARM64) || MIPS)
+ help
+ This option allows you to use the built-in libgcc implementation
+ of U-Boot instead of the one provided by the compiler.
+ If unsure, say N.
+
+config SYS_HZ
+ int
+ default 1000
+ help
+ The frequency of the timer returned by get_timer().
+ get_timer() must operate in milliseconds and this option must be
+ set to 1000.
+
+config SPL_USE_TINY_PRINTF
+ bool "Enable tiny printf() version in SPL"
+ depends on SPL
+ default y
+ help
+ This option enables a tiny, stripped down printf version.
+ This should only be used in space limited environments,
+ like SPL versions with hard memory limits. This version
+ reduces the code size by about 2.5KiB on armv7.
+
+ The supported format specifiers are %c, %s, %u/%d and %x.
+
+config TPL_USE_TINY_PRINTF
+ bool "Enable tiny printf() version in TPL"
+ depends on TPL
+ default y if SPL_USE_TINY_PRINTF
+ help
+ This option enables a tiny, stripped down printf version.
+ This should only be used in space limited environments,
+ like SPL versions with hard memory limits. This version
+ reduces the code size by about 2.5KiB on armv7.
+
+ The supported format specifiers are %c, %s, %u/%d and %x.
+
+config PANIC_HANG
+ bool "Do not reset the system on fatal error"
+ help
+ Define this option to stop the system in case of a fatal error,
+ so that you have to reset it manually. This is probably NOT a good
+ idea for an embedded system where you want the system to reboot
+ automatically as fast as possible, but it may be useful during
+ development since you can try to debug the conditions that lead to
+ the situation.
+
+config REGEX
+ bool "Enable regular expression support"
+ default y if NET
+ help
+ If this variable is defined, U-Boot is linked against the
+ SLRE (Super Light Regular Expression) library, which adds
+ regex support to some commands, for example "env grep" and
+ "setexpr".
+
+choice
+ prompt "Pseudo-random library support type"
+ depends on NET_RANDOM_ETHADDR || RANDOM_UUID || CMD_UUID
+ default LIB_RAND
+ help
+ Select the library to provide pseudo-random number generator
+ functions. LIB_HW_RAND supports certain hardware engines that
+ provide this functionality. If in doubt, select LIB_RAND.
+
+config LIB_RAND
+ bool "Pseudo-random library support"
+
+config LIB_HW_RAND
+ bool "HW Engine for random libray support"
+
+endchoice
+
+config SPL_TINY_MEMSET
+ bool "Use a very small memset() in SPL"
+ help
+ The faster memset() is the arch-specific one (if available) enabled
+ by CONFIG_USE_ARCH_MEMSET. If that is not enabled, we can still get
+ better performance by writing a word at a time. But in very
+ size-constrained environments even this may be too big. Enable this
+ option to reduce code size slightly at the cost of some speed.
+
+config TPL_TINY_MEMSET
+ bool "Use a very small memset() in TPL"
+ help
+ The faster memset() is the arch-specific one (if available) enabled
+ by CONFIG_USE_ARCH_MEMSET. If that is not enabled, we can still get
+ better performance by writing a word at a time. But in very
+ size-constrained environments even this may be too big. Enable this
+ option to reduce code size slightly at the cost of some speed.
+
+config RBTREE
+ bool
+
+config BITREVERSE
+ bool "Bit reverse library from Linux"
+
+config TRACE
+ bool "Support for tracing of function calls and timing"
+ imply CMD_TRACE
+ help
+ Enables function tracing within U-Boot. This allows recording of call
+ traces including timing information. The command can write data to
+ memory for exporting for analysis (e.g. using bootchart).
+ See doc/README.trace for full details.
+
+config TRACE_BUFFER_SIZE
+ hex "Size of trace buffer in U-Boot"
+ depends on TRACE
+ default 0x01000000
+ help
+ Sets the size of the trace buffer in U-Boot. This is allocated from
+ memory during relocation. If this buffer is too small, the trace
+ history will be truncated, with later records omitted.
+
+ If early trace is enabled (i.e. before relocation), this buffer must
+ be large enough to include all the data from the early trace buffer as
+ well, since this is copied over to the main buffer during relocation.
+
+ A trace record is emitted for each function call and each record is
+ 12 bytes (see struct trace_call). A suggested minimum size is 1MB. If
+ the size is too small then 'trace stats' will show a message saying
+ how many records were dropped due to buffer overflow.
+
+config TRACE_CALL_DEPTH_LIMIT
+ int "Trace call depth limit"
+ depends on TRACE
+ default 15
+ help
+ Sets the maximum call depth up to which function calls are recorded.
+
+config TRACE_EARLY
+ bool "Enable tracing before relocation"
+ depends on TRACE
+ help
+ Sometimes it is helpful to trace execution of U-Boot before
+ relocation. This is possible by using a arch-specific, fixed buffer
+ position in memory. Enable this option to start tracing as early as
+ possible after U-Boot starts.
+
+config TRACE_EARLY_SIZE
+ hex "Size of early trace buffer in U-Boot"
+ depends on TRACE_EARLY
+ default 0x00100000
+ help
+ Sets the size of the early trace buffer in bytes. This is used to hold
+ tracing information before relocation.
+
+config TRACE_EARLY_CALL_DEPTH_LIMIT
+ int "Early trace call depth limit"
+ depends on TRACE_EARLY
+ default 200
+ help
+ Sets the maximum call depth up to which function calls are recorded
+ during early tracing.
+
+config TRACE_EARLY_ADDR
+ hex "Address of early trace buffer in U-Boot"
+ depends on TRACE_EARLY
+ default 0x00100000
+ help
+ Sets the address of the early trace buffer in U-Boot. This memory
+ must be accessible before relocation.
+
+ A trace record is emitted for each function call and each record is
+ 12 bytes (see struct trace_call). A suggested minimum size is 1MB. If
+ the size is too small then the message which says the amount of early
+ data being coped will the the same as the
+
+source lib/dhry/Kconfig
+
+menu "Security support"
+
+config AES
+ bool "Support the AES algorithm"
+ help
+ This provides a means to encrypt and decrypt data using the AES
+ (Advanced Encryption Standard). This algorithm uses a symetric key
+ and is widely used as a streaming cipher. Different key lengths are
+ supported by the algorithm but only a 128-bit key is supported at
+ present.
+
+source lib/rsa/Kconfig
+source lib/crypto/Kconfig
+
+config TPM
+ bool "Trusted Platform Module (TPM) Support"
+ depends on DM
+ help
+ This enables support for TPMs which can be used to provide security
+ features for your board. The TPM can be connected via LPC or I2C
+ and a sandbox TPM is provided for testing purposes. Use the 'tpm'
+ command to interactive the TPM. Driver model support is provided
+ for the low-level TPM interface, but only one TPM is supported at
+ a time by the TPM library.
+
+config SPL_TPM
+ bool "Trusted Platform Module (TPM) Support in SPL"
+ depends on SPL_DM
+ help
+ This enables support for TPMs which can be used to provide security
+ features for your board. The TPM can be connected via LPC or I2C
+ and a sandbox TPM is provided for testing purposes. Use the 'tpm'
+ command to interactive the TPM. Driver model support is provided
+ for the low-level TPM interface, but only one TPM is supported at
+ a time by the TPM library.
+
+config TPL_TPM
+ bool "Trusted Platform Module (TPM) Support in TPL"
+ depends on TPL_DM
+ help
+ This enables support for TPMs which can be used to provide security
+ features for your board. The TPM can be connected via LPC or I2C
+ and a sandbox TPM is provided for testing purposes. Use the 'tpm'
+ command to interactive the TPM. Driver model support is provided
+ for the low-level TPM interface, but only one TPM is supported at
+ a time by the TPM library.
+
+endmenu
+
+menu "Android Verified Boot"
+
+config LIBAVB
+ bool "Android Verified Boot 2.0 support"
+ depends on ANDROID_BOOT_IMAGE
+ default n
+ help
+ This enables support of Android Verified Boot 2.0 which can be used
+ to assure the end user of the integrity of the software running on a
+ device. Introduces such features as boot chain of trust, rollback
+ protection etc.
+
+endmenu
+
+menu "Hashing Support"
+
+config SHA1
+ bool "Enable SHA1 support"
+ help
+ This option enables support of hashing using SHA1 algorithm.
+ The hash is calculated in software.
+ The SHA1 algorithm produces a 160-bit (20-byte) hash value
+ (digest).
+
+config SHA256
+ bool "Enable SHA256 support"
+ help
+ This option enables support of hashing using SHA256 algorithm.
+ The hash is calculated in software.
+ The SHA256 algorithm produces a 256-bit (32-byte) hash value
+ (digest).
+
+config SHA_HW_ACCEL
+ bool "Enable hashing using hardware"
+ help
+ This option enables hardware acceleration
+ for SHA1/SHA256 hashing.
+ This affects the 'hash' command and also the
+ hash_lookup_algo() function.
+
+config SHA_PROG_HW_ACCEL
+ bool "Enable Progressive hashing support using hardware"
+ depends on SHA_HW_ACCEL
+ help
+ This option enables hardware-acceleration for
+ SHA1/SHA256 progressive hashing.
+ Data can be streamed in a block at a time and the hashing
+ is performed in hardware.
+
+config MD5
+ bool
+
+config CRC32C
+ bool
+
+config XXHASH
+ bool
+
+endmenu
+
+menu "Compression Support"
+
+config LZ4
+ bool "Enable LZ4 decompression support"
+ help
+ If this option is set, support for LZ4 compressed images
+ is included. The LZ4 algorithm can run in-place as long as the
+ compressed image is loaded to the end of the output buffer, and
+ trades lower compression ratios for much faster decompression.
+
+ NOTE: This implements the release version of the LZ4 frame
+ format as generated by default by the 'lz4' command line tool.
+ This is not the same as the outdated, less efficient legacy
+ frame format currently (2015) implemented in the Linux kernel
+ (generated by 'lz4 -l'). The two formats are incompatible.
+
+config LZMA
+ bool "Enable LZMA decompression support"
+ help
+ This enables support for LZMA (Lempel-Ziv-Markov chain algorithm),
+ a dictionary compression algorithm that provides a high compression
+ ratio and fairly fast decompression speed. See also
+ CONFIG_CMD_LZMADEC which provides a decode command.
+
+config LZO
+ bool "Enable LZO decompression support"
+ help
+ This enables support for LZO compression algorithm.r
+
+config GZIP
+ bool "Enable gzip decompression support"
+ select ZLIB
+ default y
+ help
+ This enables support for GZIP compression algorithm.
+
+config ZLIB
+ bool
+ default y
+ help
+ This enables ZLIB compression lib.
+
+config ZSTD
+ bool "Enable Zstandard decompression support"
+ select XXHASH
+ help
+ This enables Zstandard decompression library.
+
+config SPL_LZ4
+ bool "Enable LZ4 decompression support in SPL"
+ help
+ This enables support for tge LZ4 decompression algorithm in SPL. LZ4
+ is a lossless data compression algorithm that is focused on
+ fast compression and decompression speed. It belongs to the LZ77
+ family of byte-oriented compression schemes.
+
+config SPL_LZO
+ bool "Enable LZO decompression support in SPL"
+ help
+ This enables support for LZO compression algorithm in the SPL.
+
+config SPL_GZIP
+ bool "Enable gzip decompression support for SPL build"
+ select SPL_ZLIB
+ help
+ This enables support for GZIP compression altorithm for SPL boot.
+
+config SPL_ZLIB
+ bool
+ help
+ This enables compression lib for SPL boot.
+
+config SPL_ZSTD
+ bool "Enable Zstandard decompression support in SPL"
+ select XXHASH
+ help
+ This enables Zstandard decompression library in the SPL.
+
+endmenu
+
+config ERRNO_STR
+ bool "Enable function for getting errno-related string message"
+ help
+ The function errno_str(int errno), returns a pointer to the errno
+ corresponding text message:
+ - if errno is null or positive number - a pointer to "Success" message
+ - if errno is negative - a pointer to errno related message
+
+config HEXDUMP
+ bool "Enable hexdump"
+ help
+ This enables functions for printing dumps of binary data.
+
+config OF_LIBFDT
+ bool "Enable the FDT library"
+ default y if OF_CONTROL
+ help
+ This enables the FDT library (libfdt). It provides functions for
+ accessing binary device tree images in memory, such as adding and
+ removing nodes and properties, scanning through the tree and finding
+ particular compatible nodes. The library operates on a flattened
+ version of the device tree.
+
+config OF_LIBFDT_ASSUME_MASK
+ hex "Mask of conditions to assume for libfdt"
+ depends on OF_LIBFDT || FIT
+ default 0
+ help
+ Use this to change the assumptions made by libfdt about the
+ device tree it is working with. A value of 0 means that no assumptions
+ are made, and libfdt is able to deal with malicious data. A value of
+ 0xff means all assumptions are made and any invalid data may cause
+ unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
+config OF_LIBFDT_OVERLAY
+ bool "Enable the FDT library overlay support"
+ depends on OF_LIBFDT
+ default y if ARCH_OMAP2PLUS || ARCH_KEYSTONE
+ help
+ This enables the FDT library (libfdt) overlay support.
+
+config SPL_OF_LIBFDT
+ bool "Enable the FDT library for SPL"
+ default y if SPL_OF_CONTROL
+ help
+ This enables the FDT library (libfdt). It provides functions for
+ accessing binary device tree images in memory, such as adding and
+ removing nodes and properties, scanning through the tree and finding
+ particular compatible nodes. The library operates on a flattened
+ version of the device tree.
+
+config SPL_OF_LIBFDT_ASSUME_MASK
+ hex "Mask of conditions to assume for libfdt"
+ depends on SPL_OF_LIBFDT || FIT
+ default 0xff
+ help
+ Use this to change the assumptions made by libfdt in SPL about the
+ device tree it is working with. A value of 0 means that no assumptions
+ are made, and libfdt is able to deal with malicious data. A value of
+ 0xff means all assumptions are made and any invalid data may cause
+ unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
+config TPL_OF_LIBFDT
+ bool "Enable the FDT library for TPL"
+ default y if TPL_OF_CONTROL
+ help
+ This enables the FDT library (libfdt). It provides functions for
+ accessing binary device tree images in memory, such as adding and
+ removing nodes and properties, scanning through the tree and finding
+ particular compatible nodes. The library operates on a flattened
+ version of the device tree.
+
+config TPL_OF_LIBFDT_ASSUME_MASK
+ hex "Mask of conditions to assume for libfdt"
+ depends on TPL_OF_LIBFDT || FIT
+ default 0xff
+ help
+ Use this to change the assumptions made by libfdt in TPL about the
+ device tree it is working with. A value of 0 means that no assumptions
+ are made, and libfdt is able to deal with malicious data. A value of
+ 0xff means all assumptions are made and any invalid data may cause
+ unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
+config FDT_FIXUP_PARTITIONS
+ bool "overwrite MTD partitions in DTS through defined in 'mtdparts'"
+ depends on OF_LIBFDT
+ depends on CMD_MTDPARTS
+ help
+ Allow overwriting defined partitions in the device tree blob
+ using partition info defined in the 'mtdparts' environment
+ variable.
+
+menu "System tables"
+ depends on (!EFI && !SYS_COREBOOT) || (ARM && EFI_LOADER)
+
+config GENERATE_SMBIOS_TABLE
+ bool "Generate an SMBIOS (System Management BIOS) table"
+ default y
+ depends on X86 || EFI_LOADER
+ help
+ The System Management BIOS (SMBIOS) specification addresses how
+ motherboard and system vendors present management information about
+ their products in a standard format by extending the BIOS interface
+ on Intel architecture systems.
+
+ Check http://www.dmtf.org/standards/smbios for details.
+
+config SMBIOS_MANUFACTURER
+ string "SMBIOS Manufacturer"
+ depends on GENERATE_SMBIOS_TABLE
+ default SYS_VENDOR
+ help
+ The board manufacturer to store in SMBIOS structures.
+ Change this to override the default one (CONFIG_SYS_VENDOR).
+
+config SMBIOS_PRODUCT_NAME
+ string "SMBIOS Product Name"
+ depends on GENERATE_SMBIOS_TABLE
+ default SYS_BOARD
+ help
+ The product name to store in SMBIOS structures.
+ Change this to override the default one (CONFIG_SYS_BOARD).
+
+endmenu
+
+config ASN1_COMPILER
+ bool
+
+config ASN1_DECODER
+ bool
+ help
+ Enable asn1 decoder library.
+
+config OID_REGISTRY
+ bool
+ help
+ Enable fast lookup object identifier registry.
+
+source lib/efi/Kconfig
+source lib/efi_loader/Kconfig
+source lib/optee/Kconfig
+
+config TEST_FDTDEC
+ bool "enable fdtdec test"
+ depends on OF_LIBFDT
+
+config LIB_DATE
+ bool
+
+endmenu
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 00000000..1fb650cd
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,140 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ifndef CONFIG_SPL_BUILD
+
+obj-$(CONFIG_EFI) += efi/
+obj-$(CONFIG_EFI_LOADER) += efi_driver/
+obj-$(CONFIG_EFI_LOADER) += efi_loader/
+obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
+obj-$(CONFIG_LZMA) += lzma/
+obj-$(CONFIG_BZIP2) += bzip2/
+obj-$(CONFIG_TIZEN) += tizen/
+obj-$(CONFIG_FIT) += libfdt/
+obj-$(CONFIG_OF_LIVE) += of_live.o
+obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
+obj-$(CONFIG_ARCH_AT91) += at91/
+obj-$(CONFIG_OPTEE) += optee/
+obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o
+obj-y += crypto/
+
+obj-$(CONFIG_AES) += aes.o
+
+ifndef API_BUILD
+ifneq ($(CONFIG_UT_UNICODE)$(CONFIG_EFI_LOADER),)
+obj-y += charset.o
+endif
+endif
+obj-$(CONFIG_USB_TTY) += circbuf.o
+obj-y += crc7.o
+obj-y += crc8.o
+obj-y += crc16.o
+obj-$(CONFIG_ERRNO_STR) += errno_str.o
+obj-$(CONFIG_FIT) += fdtdec_common.o
+obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
+obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
+obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
+obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
+obj-y += ldiv.o
+obj-$(CONFIG_MD5) += md5.o
+obj-$(CONFIG_XXHASH) += xxhash.o
+obj-y += net_utils.o
+obj-$(CONFIG_PHYSMEM) += physmem.o
+obj-y += rc4.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
+obj-$(CONFIG_RBTREE) += rbtree.o
+obj-$(CONFIG_BITREVERSE) += bitrev.o
+obj-y += list_sort.o
+endif
+
+obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o
+ifeq ($(CONFIG_$(SPL_TPL_)TPM),y)
+obj-y += crc8.o
+obj-$(CONFIG_TPM_V1) += tpm-v1.o
+obj-$(CONFIG_TPM_V2) += tpm-v2.o
+endif
+
+obj-$(CONFIG_RSA) += rsa/
+obj-$(CONFIG_SHA1) += sha1.o
+obj-$(CONFIG_SHA256) += sha256.o
+
+obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
+obj-$(CONFIG_$(SPL_)ZSTD) += zstd/
+obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
+obj-$(CONFIG_$(SPL_)LZO) += lzo/
+obj-$(CONFIG_$(SPL_)LZ4) += lz4_wrapper.o
+
+obj-$(CONFIG_LIBAVB) += libavb/
+
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
+ifneq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
+obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec_common.o
+obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec.o
+endif
+
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
+obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o
+obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
+endif
+obj-$(CONFIG_ADDR_MAP) += addr_map.o
+obj-y += qsort.o
+obj-y += hashtable.o
+obj-y += errno.o
+obj-y += display_options.o
+CFLAGS_display_options.o := $(if $(BUILD_TAG),-DBUILD_TAG='"$(BUILD_TAG)"')
+obj-$(CONFIG_BCH) += bch.o
+obj-y += crc32.o
+obj-$(CONFIG_CRC32C) += crc32c.o
+obj-y += ctype.o
+obj-y += div64.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdtdec.o fdtdec_common.o
+obj-y += hang.o
+obj-y += linux_compat.o
+obj-y += linux_string.o
+obj-$(CONFIG_LMB) += lmb.o
+obj-y += membuff.o
+obj-$(CONFIG_REGEX) += slre.o
+obj-y += string.o
+obj-y += tables_csum.o
+obj-y += time.o
+obj-y += hexdump.o
+obj-$(CONFIG_TRACE) += trace.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
+obj-$(CONFIG_LIB_RAND) += rand.o
+obj-y += panic.o
+
+ifeq ($(CONFIG_$(SPL_TPL_)BUILD),y)
+# SPL U-Boot may use full-printf, tiny-printf or none at all
+ifdef CONFIG_$(SPL_TPL_)USE_TINY_PRINTF
+obj-$(CONFIG_$(SPL_TPL_)SPRINTF) += tiny-printf.o
+else
+obj-$(CONFIG_$(SPL_TPL_)SPRINTF) += vsprintf.o
+endif
+obj-$(CONFIG_$(SPL_TPL_)STRTO) += strto.o
+else
+# Main U-Boot always uses the full printf support
+obj-y += vsprintf.o strto.o
+endif
+
+obj-y += date.o
+
+#
+# Build a fast OID lookup registry from include/linux/oid_registry.h
+#
+obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
+
+$(obj)/oid_registry.o: $(obj)/oid_registry_data.c
+
+$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \
+ $(srctree)/scripts/build_OID_registry
+ $(call cmd,build_OID_registry)
+
+quiet_cmd_build_OID_registry = GEN $@
+ cmd_build_OID_registry = perl $(srctree)/scripts/build_OID_registry $< $@
+
+clean-files += oid_registry_data.c
+
+subdir-ccflags-$(CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED) += -O2
diff --git a/lib/addr_map.c b/lib/addr_map.c
new file mode 100644
index 00000000..09771f3a
--- /dev/null
+++ b/lib/addr_map.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <addr_map.h>
+
+static struct {
+ phys_addr_t paddr;
+ phys_size_t size;
+ unsigned long vaddr;
+} address_map[CONFIG_SYS_NUM_ADDR_MAP];
+
+phys_addr_t addrmap_virt_to_phys(void * vaddr)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++) {
+ u64 base, upper, addr;
+
+ if (address_map[i].size == 0)
+ continue;
+
+ addr = (u64)((u32)vaddr);
+ base = (u64)(address_map[i].vaddr);
+ upper = (u64)(address_map[i].size) + base - 1;
+
+ if (addr >= base && addr <= upper) {
+ return addr - address_map[i].vaddr + address_map[i].paddr;
+ }
+ }
+
+ return (phys_addr_t)(~0);
+}
+
+void *addrmap_phys_to_virt(phys_addr_t paddr)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++) {
+ phys_addr_t base, upper;
+
+ if (address_map[i].size == 0)
+ continue;
+
+ base = address_map[i].paddr;
+ upper = address_map[i].size + base - 1;
+
+ if (paddr >= base && paddr <= upper) {
+ phys_addr_t offset;
+
+ offset = address_map[i].paddr - address_map[i].vaddr;
+
+ return (void *)(unsigned long)(paddr - offset);
+ }
+ }
+
+ return (void *)(~0);
+}
+
+void addrmap_set_entry(unsigned long vaddr, phys_addr_t paddr,
+ phys_size_t size, int idx)
+{
+ if (idx > CONFIG_SYS_NUM_ADDR_MAP)
+ return;
+
+ address_map[idx].vaddr = vaddr;
+ address_map[idx].paddr = paddr;
+ address_map[idx].size = size;
+}
diff --git a/lib/aes.c b/lib/aes.c
new file mode 100644
index 00000000..a12a1920
--- /dev/null
+++ b/lib/aes.c
@@ -0,0 +1,657 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2011 NVIDIA Corporation www.nvidia.com
+ */
+
+/*
+ * advanced encryption standard
+ * author: karl malbrain, malbrain@yahoo.com
+ *
+ * This work, including the source code, documentation
+ * and related data, is placed into the public domain.
+ *
+ * The orginal author is Karl Malbrain.
+ *
+ * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+ * OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+ * MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ * ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+ * RESULTING FROM THE USE, MODIFICATION, OR
+ * REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#else
+#include <string.h>
+#endif
+#include "uboot_aes.h"
+
+/* forward s-box */
+static const u8 sbox[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+/* inverse s-box */
+static const u8 inv_sbox[256] = {
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+/* combined Xtimes2[Sbox[]] */
+static const u8 x2_sbox[256] = {
+ 0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91,
+ 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
+ 0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb,
+ 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
+ 0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83,
+ 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
+ 0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f,
+ 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
+ 0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b,
+ 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
+ 0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6,
+ 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
+ 0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11,
+ 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
+ 0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1,
+ 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
+ 0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e,
+ 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
+ 0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b,
+ 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
+ 0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8,
+ 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
+ 0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49,
+ 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
+ 0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97,
+ 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
+ 0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c,
+ 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
+ 0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33,
+ 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
+ 0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0,
+ 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
+};
+
+/* combined Xtimes3[Sbox[]] */
+static const u8 x3_sbox[256] = {
+ 0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54,
+ 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
+ 0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b,
+ 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
+ 0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f,
+ 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
+ 0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5,
+ 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
+ 0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb,
+ 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
+ 0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed,
+ 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
+ 0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94,
+ 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
+ 0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04,
+ 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
+ 0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39,
+ 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
+ 0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83,
+ 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
+ 0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4,
+ 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
+ 0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0,
+ 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
+ 0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51,
+ 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
+ 0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12,
+ 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
+ 0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7,
+ 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
+ 0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8,
+ 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
+};
+
+/*
+ * modular multiplication tables based on:
+ *
+ * Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
+ * Xtime3[x] = x^Xtime2[x];
+ */
+static const u8 x_time_9[256] = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+ 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf,
+ 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+ 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94,
+ 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
+ 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49,
+ 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
+ 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9,
+ 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
+ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72,
+ 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
+ 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2,
+ 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
+ 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3,
+ 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
+ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43,
+ 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
+ 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8,
+ 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
+ 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78,
+ 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
+ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5,
+ 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
+ 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35,
+ 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
+ 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e,
+ 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
+ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e,
+ 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
+};
+
+static const u8 x_time_b[256] = {
+ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31,
+ 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
+ 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81,
+ 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
+ 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a,
+ 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
+ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa,
+ 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
+ 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7,
+ 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
+ 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77,
+ 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
+ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc,
+ 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
+ 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c,
+ 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
+ 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6,
+ 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
+ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76,
+ 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
+ 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd,
+ 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
+ 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d,
+ 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
+ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30,
+ 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
+ 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80,
+ 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
+ 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b,
+ 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
+ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb,
+ 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
+};
+
+static const u8 x_time_d[256] = {
+ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23,
+ 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
+ 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3,
+ 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
+ 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98,
+ 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
+ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48,
+ 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
+ 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e,
+ 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
+ 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e,
+ 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
+ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5,
+ 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
+ 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25,
+ 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
+ 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9,
+ 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
+ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29,
+ 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
+ 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42,
+ 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
+ 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92,
+ 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
+ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94,
+ 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
+ 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44,
+ 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
+ 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f,
+ 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
+ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff,
+ 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
+};
+
+static const u8 x_time_e[256] = {
+ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a,
+ 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
+ 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca,
+ 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
+ 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1,
+ 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
+ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11,
+ 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
+ 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87,
+ 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
+ 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67,
+ 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
+ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c,
+ 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
+ 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc,
+ 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
+ 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b,
+ 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
+ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b,
+ 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
+ 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0,
+ 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
+ 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50,
+ 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
+ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6,
+ 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
+ 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26,
+ 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
+ 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d,
+ 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
+ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd,
+ 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
+};
+
+/*
+ * Exchanges columns in each of 4 rows
+ * row0 - unchanged, row1- shifted left 1,
+ * row2 - shifted left 2 and row3 - shifted left 3
+ */
+static void shift_rows(u8 *state)
+{
+ u8 tmp;
+
+ /* just substitute row 0 */
+ state[0] = sbox[state[0]];
+ state[4] = sbox[state[4]];
+ state[8] = sbox[state[8]];
+ state[12] = sbox[state[12]];
+
+ /* rotate row 1 */
+ tmp = sbox[state[1]];
+ state[1] = sbox[state[5]];
+ state[5] = sbox[state[9]];
+ state[9] = sbox[state[13]];
+ state[13] = tmp;
+
+ /* rotate row 2 */
+ tmp = sbox[state[2]];
+ state[2] = sbox[state[10]];
+ state[10] = tmp;
+ tmp = sbox[state[6]];
+ state[6] = sbox[state[14]];
+ state[14] = tmp;
+
+ /* rotate row 3 */
+ tmp = sbox[state[15]];
+ state[15] = sbox[state[11]];
+ state[11] = sbox[state[7]];
+ state[7] = sbox[state[3]];
+ state[3] = tmp;
+}
+
+/*
+ * restores columns in each of 4 rows
+ * row0 - unchanged, row1- shifted right 1,
+ * row2 - shifted right 2 and row3 - shifted right 3
+ */
+static void inv_shift_rows(u8 *state)
+{
+ u8 tmp;
+
+ /* restore row 0 */
+ state[0] = inv_sbox[state[0]];
+ state[4] = inv_sbox[state[4]];
+ state[8] = inv_sbox[state[8]];
+ state[12] = inv_sbox[state[12]];
+
+ /* restore row 1 */
+ tmp = inv_sbox[state[13]];
+ state[13] = inv_sbox[state[9]];
+ state[9] = inv_sbox[state[5]];
+ state[5] = inv_sbox[state[1]];
+ state[1] = tmp;
+
+ /* restore row 2 */
+ tmp = inv_sbox[state[2]];
+ state[2] = inv_sbox[state[10]];
+ state[10] = tmp;
+ tmp = inv_sbox[state[6]];
+ state[6] = inv_sbox[state[14]];
+ state[14] = tmp;
+
+ /* restore row 3 */
+ tmp = inv_sbox[state[3]];
+ state[3] = inv_sbox[state[7]];
+ state[7] = inv_sbox[state[11]];
+ state[11] = inv_sbox[state[15]];
+ state[15] = tmp;
+}
+
+/* recombine and mix each row in a column */
+static void mix_sub_columns(u8 *state)
+{
+ u8 tmp[4 * AES_STATECOLS];
+
+ /* mixing column 0 */
+ tmp[0] = x2_sbox[state[0]] ^ x3_sbox[state[5]] ^
+ sbox[state[10]] ^ sbox[state[15]];
+ tmp[1] = sbox[state[0]] ^ x2_sbox[state[5]] ^
+ x3_sbox[state[10]] ^ sbox[state[15]];
+ tmp[2] = sbox[state[0]] ^ sbox[state[5]] ^
+ x2_sbox[state[10]] ^ x3_sbox[state[15]];
+ tmp[3] = x3_sbox[state[0]] ^ sbox[state[5]] ^
+ sbox[state[10]] ^ x2_sbox[state[15]];
+
+ /* mixing column 1 */
+ tmp[4] = x2_sbox[state[4]] ^ x3_sbox[state[9]] ^
+ sbox[state[14]] ^ sbox[state[3]];
+ tmp[5] = sbox[state[4]] ^ x2_sbox[state[9]] ^
+ x3_sbox[state[14]] ^ sbox[state[3]];
+ tmp[6] = sbox[state[4]] ^ sbox[state[9]] ^
+ x2_sbox[state[14]] ^ x3_sbox[state[3]];
+ tmp[7] = x3_sbox[state[4]] ^ sbox[state[9]] ^
+ sbox[state[14]] ^ x2_sbox[state[3]];
+
+ /* mixing column 2 */
+ tmp[8] = x2_sbox[state[8]] ^ x3_sbox[state[13]] ^
+ sbox[state[2]] ^ sbox[state[7]];
+ tmp[9] = sbox[state[8]] ^ x2_sbox[state[13]] ^
+ x3_sbox[state[2]] ^ sbox[state[7]];
+ tmp[10] = sbox[state[8]] ^ sbox[state[13]] ^
+ x2_sbox[state[2]] ^ x3_sbox[state[7]];
+ tmp[11] = x3_sbox[state[8]] ^ sbox[state[13]] ^
+ sbox[state[2]] ^ x2_sbox[state[7]];
+
+ /* mixing column 3 */
+ tmp[12] = x2_sbox[state[12]] ^ x3_sbox[state[1]] ^
+ sbox[state[6]] ^ sbox[state[11]];
+ tmp[13] = sbox[state[12]] ^ x2_sbox[state[1]] ^
+ x3_sbox[state[6]] ^ sbox[state[11]];
+ tmp[14] = sbox[state[12]] ^ sbox[state[1]] ^
+ x2_sbox[state[6]] ^ x3_sbox[state[11]];
+ tmp[15] = x3_sbox[state[12]] ^ sbox[state[1]] ^
+ sbox[state[6]] ^ x2_sbox[state[11]];
+
+ memcpy(state, tmp, sizeof(tmp));
+}
+
+/* restore and un-mix each row in a column */
+static void inv_mix_sub_columns(u8 *state)
+{
+ u8 tmp[4 * AES_STATECOLS];
+ int i;
+
+ /* restore column 0 */
+ tmp[0] = x_time_e[state[0]] ^ x_time_b[state[1]] ^
+ x_time_d[state[2]] ^ x_time_9[state[3]];
+ tmp[5] = x_time_9[state[0]] ^ x_time_e[state[1]] ^
+ x_time_b[state[2]] ^ x_time_d[state[3]];
+ tmp[10] = x_time_d[state[0]] ^ x_time_9[state[1]] ^
+ x_time_e[state[2]] ^ x_time_b[state[3]];
+ tmp[15] = x_time_b[state[0]] ^ x_time_d[state[1]] ^
+ x_time_9[state[2]] ^ x_time_e[state[3]];
+
+ /* restore column 1 */
+ tmp[4] = x_time_e[state[4]] ^ x_time_b[state[5]] ^
+ x_time_d[state[6]] ^ x_time_9[state[7]];
+ tmp[9] = x_time_9[state[4]] ^ x_time_e[state[5]] ^
+ x_time_b[state[6]] ^ x_time_d[state[7]];
+ tmp[14] = x_time_d[state[4]] ^ x_time_9[state[5]] ^
+ x_time_e[state[6]] ^ x_time_b[state[7]];
+ tmp[3] = x_time_b[state[4]] ^ x_time_d[state[5]] ^
+ x_time_9[state[6]] ^ x_time_e[state[7]];
+
+ /* restore column 2 */
+ tmp[8] = x_time_e[state[8]] ^ x_time_b[state[9]] ^
+ x_time_d[state[10]] ^ x_time_9[state[11]];
+ tmp[13] = x_time_9[state[8]] ^ x_time_e[state[9]] ^
+ x_time_b[state[10]] ^ x_time_d[state[11]];
+ tmp[2] = x_time_d[state[8]] ^ x_time_9[state[9]] ^
+ x_time_e[state[10]] ^ x_time_b[state[11]];
+ tmp[7] = x_time_b[state[8]] ^ x_time_d[state[9]] ^
+ x_time_9[state[10]] ^ x_time_e[state[11]];
+
+ /* restore column 3 */
+ tmp[12] = x_time_e[state[12]] ^ x_time_b[state[13]] ^
+ x_time_d[state[14]] ^ x_time_9[state[15]];
+ tmp[1] = x_time_9[state[12]] ^ x_time_e[state[13]] ^
+ x_time_b[state[14]] ^ x_time_d[state[15]];
+ tmp[6] = x_time_d[state[12]] ^ x_time_9[state[13]] ^
+ x_time_e[state[14]] ^ x_time_b[state[15]];
+ tmp[11] = x_time_b[state[12]] ^ x_time_d[state[13]] ^
+ x_time_9[state[14]] ^ x_time_e[state[15]];
+
+ for (i = 0; i < 4 * AES_STATECOLS; i++)
+ state[i] = inv_sbox[tmp[i]];
+}
+
+/*
+ * encrypt/decrypt columns of the key
+ * n.b. you can replace this with byte-wise xor if you wish.
+ */
+static void add_round_key(u32 *state, u32 *key)
+{
+ int idx;
+
+ for (idx = 0; idx < 4; idx++)
+ state[idx] ^= key[idx];
+}
+
+static u8 rcon[11] = {
+ 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
+};
+
+/* produce AES_STATECOLS bytes for each round */
+void aes_expand_key(u8 *key, u8 *expkey)
+{
+ u8 tmp0, tmp1, tmp2, tmp3, tmp4;
+ u32 idx;
+
+ memcpy(expkey, key, AES_KEYCOLS * 4);
+
+ for (idx = AES_KEYCOLS; idx < AES_STATECOLS * (AES_ROUNDS + 1); idx++) {
+ tmp0 = expkey[4*idx - 4];
+ tmp1 = expkey[4*idx - 3];
+ tmp2 = expkey[4*idx - 2];
+ tmp3 = expkey[4*idx - 1];
+ if (!(idx % AES_KEYCOLS)) {
+ tmp4 = tmp3;
+ tmp3 = sbox[tmp0];
+ tmp0 = sbox[tmp1] ^ rcon[idx / AES_KEYCOLS];
+ tmp1 = sbox[tmp2];
+ tmp2 = sbox[tmp4];
+ } else if ((AES_KEYCOLS > 6) && (idx % AES_KEYCOLS == 4)) {
+ tmp0 = sbox[tmp0];
+ tmp1 = sbox[tmp1];
+ tmp2 = sbox[tmp2];
+ tmp3 = sbox[tmp3];
+ }
+
+ expkey[4*idx+0] = expkey[4*idx - 4*AES_KEYCOLS + 0] ^ tmp0;
+ expkey[4*idx+1] = expkey[4*idx - 4*AES_KEYCOLS + 1] ^ tmp1;
+ expkey[4*idx+2] = expkey[4*idx - 4*AES_KEYCOLS + 2] ^ tmp2;
+ expkey[4*idx+3] = expkey[4*idx - 4*AES_KEYCOLS + 3] ^ tmp3;
+ }
+}
+
+/* encrypt one 128 bit block */
+void aes_encrypt(u8 *in, u8 *expkey, u8 *out)
+{
+ u8 state[AES_STATECOLS * 4];
+ u32 round;
+
+ memcpy(state, in, AES_STATECOLS * 4);
+ add_round_key((u32 *)state, (u32 *)expkey);
+
+ for (round = 1; round < AES_ROUNDS + 1; round++) {
+ if (round < AES_ROUNDS)
+ mix_sub_columns(state);
+ else
+ shift_rows(state);
+
+ add_round_key((u32 *)state,
+ (u32 *)expkey + round * AES_STATECOLS);
+ }
+
+ memcpy(out, state, sizeof(state));
+}
+
+void aes_decrypt(u8 *in, u8 *expkey, u8 *out)
+{
+ u8 state[AES_STATECOLS * 4];
+ int round;
+
+ memcpy(state, in, sizeof(state));
+
+ add_round_key((u32 *)state,
+ (u32 *)expkey + AES_ROUNDS * AES_STATECOLS);
+ inv_shift_rows(state);
+
+ for (round = AES_ROUNDS; round--; ) {
+ add_round_key((u32 *)state,
+ (u32 *)expkey + round * AES_STATECOLS);
+ if (round)
+ inv_mix_sub_columns(state);
+ }
+
+ memcpy(out, state, sizeof(state));
+}
+
+static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
+{
+#ifdef DEBUG
+ printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+ print_buffer(0, data, 1, num_bytes, 16);
+#endif
+}
+
+void aes_apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
+{
+ int i;
+
+ for (i = 0; i < AES_KEY_LENGTH; i++)
+ *dst++ = *src++ ^ *cbc_chain_data++;
+}
+
+void aes_cbc_encrypt_blocks(u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
+ u32 num_aes_blocks)
+{
+ u8 tmp_data[AES_KEY_LENGTH];
+ u8 *cbc_chain_data = iv;
+ u32 i;
+
+ for (i = 0; i < num_aes_blocks; i++) {
+ debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
+ debug_print_vector("AES Src", AES_KEY_LENGTH, src);
+
+ /* Apply the chain data */
+ aes_apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
+ debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
+
+ /* Encrypt the AES block */
+ aes_encrypt(tmp_data, key_exp, dst);
+ debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
+
+ /* Update pointers for next loop. */
+ cbc_chain_data = dst;
+ src += AES_KEY_LENGTH;
+ dst += AES_KEY_LENGTH;
+ }
+}
+
+void aes_cbc_decrypt_blocks(u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
+ u32 num_aes_blocks)
+{
+ u8 tmp_data[AES_KEY_LENGTH], tmp_block[AES_KEY_LENGTH];
+ /* Convenient array of 0's for IV */
+ u8 cbc_chain_data[AES_KEY_LENGTH];
+ u32 i;
+
+ memcpy(cbc_chain_data, iv, AES_KEY_LENGTH);
+ for (i = 0; i < num_aes_blocks; i++) {
+ debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
+ debug_print_vector("AES Src", AES_KEY_LENGTH, src);
+
+ memcpy(tmp_block, src, AES_KEY_LENGTH);
+
+ /* Decrypt the AES block */
+ aes_decrypt(src, key_exp, tmp_data);
+ debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
+
+ /* Apply the chain data */
+ aes_apply_cbc_chain_data(cbc_chain_data, tmp_data, dst);
+ debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
+
+ /* Update pointers for next loop. */
+ memcpy(cbc_chain_data, tmp_block, AES_KEY_LENGTH);
+ src += AES_KEY_LENGTH;
+ dst += AES_KEY_LENGTH;
+ }
+}
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
new file mode 100644
index 00000000..26175132
--- /dev/null
+++ b/lib/asm-offsets.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Adapted from Linux v2.6.36 kernel: arch/powerpc/kernel/asm-offsets.c
+ *
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <common.h>
+
+#include <linux/kbuild.h>
+
+int main(void)
+{
+ /* Round up to make sure size gives nice stack alignment */
+ DEFINE(GENERATED_GBL_DATA_SIZE,
+ (sizeof(struct global_data) + 15) & ~15);
+
+ DEFINE(GENERATED_BD_INFO_SIZE,
+ (sizeof(struct bd_info) + 15) & ~15);
+
+ DEFINE(GD_SIZE, sizeof(struct global_data));
+
+ DEFINE(GD_BD, offsetof(struct global_data, bd));
+#if CONFIG_VAL(SYS_MALLOC_F_LEN)
+ DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base));
+#endif
+
+ DEFINE(GD_RELOCADDR, offsetof(struct global_data, relocaddr));
+
+ DEFINE(GD_RELOC_OFF, offsetof(struct global_data, reloc_off));
+
+ DEFINE(GD_START_ADDR_SP, offsetof(struct global_data, start_addr_sp));
+
+ DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd));
+
+ return 0;
+}
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c
new file mode 100644
index 00000000..db222625
--- /dev/null
+++ b/lib/asn1_decoder.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Decoder for ASN.1 BER/DER/CER encoded bytestream
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#ifdef __UBOOT__
+#include <linux/compat.h>
+#else
+#include <linux/export.h>
+#endif
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#ifndef __UBOOT__
+#include <linux/module.h>
+#endif
+#include <linux/asn1_decoder.h>
+#include <linux/asn1_ber_bytecode.h>
+
+static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
+ /* OPC TAG JMP ACT */
+ [ASN1_OP_MATCH] = 1 + 1,
+ [ASN1_OP_MATCH_OR_SKIP] = 1 + 1,
+ [ASN1_OP_MATCH_ACT] = 1 + 1 + 1,
+ [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
+ [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1,
+ [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
+ [ASN1_OP_MATCH_ANY] = 1,
+ [ASN1_OP_MATCH_ANY_OR_SKIP] = 1,
+ [ASN1_OP_MATCH_ANY_ACT] = 1 + 1,
+ [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
+ [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1,
+ [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
+ [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
+ [ASN1_OP_COND_MATCH_ANY] = 1,
+ [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1,
+ [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1,
+ [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
+ [ASN1_OP_COND_FAIL] = 1,
+ [ASN1_OP_COMPLETE] = 1,
+ [ASN1_OP_ACT] = 1 + 1,
+ [ASN1_OP_MAYBE_ACT] = 1 + 1,
+ [ASN1_OP_RETURN] = 1,
+ [ASN1_OP_END_SEQ] = 1,
+ [ASN1_OP_END_SEQ_OF] = 1 + 1,
+ [ASN1_OP_END_SET] = 1,
+ [ASN1_OP_END_SET_OF] = 1 + 1,
+ [ASN1_OP_END_SEQ_ACT] = 1 + 1,
+ [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1,
+ [ASN1_OP_END_SET_ACT] = 1 + 1,
+ [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1,
+};
+
+/*
+ * Find the length of an indefinite length object
+ * @data: The data buffer
+ * @datalen: The end of the innermost containing element in the buffer
+ * @_dp: The data parse cursor (updated before returning)
+ * @_len: Where to return the size of the element.
+ * @_errmsg: Where to return a pointer to an error message on error
+ */
+static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
+ size_t *_dp, size_t *_len,
+ const char **_errmsg)
+{
+ unsigned char tag, tmp;
+ size_t dp = *_dp, len, n;
+ int indef_level = 1;
+
+next_tag:
+ if (unlikely(datalen - dp < 2)) {
+ if (datalen == dp)
+ goto missing_eoc;
+ goto data_overrun_error;
+ }
+
+ /* Extract a tag from the data */
+ tag = data[dp++];
+ if (tag == ASN1_EOC) {
+ /* It appears to be an EOC. */
+ if (data[dp++] != 0)
+ goto invalid_eoc;
+ if (--indef_level <= 0) {
+ *_len = dp - *_dp;
+ *_dp = dp;
+ return 0;
+ }
+ goto next_tag;
+ }
+
+ if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) {
+ do {
+ if (unlikely(datalen - dp < 2))
+ goto data_overrun_error;
+ tmp = data[dp++];
+ } while (tmp & 0x80);
+ }
+
+ /* Extract the length */
+ len = data[dp++];
+ if (len <= 0x7f)
+ goto check_length;
+
+ if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
+ /* Indefinite length */
+ if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
+ goto indefinite_len_primitive;
+ indef_level++;
+ goto next_tag;
+ }
+
+ n = len - 0x80;
+ if (unlikely(n > sizeof(len) - 1))
+ goto length_too_long;
+ if (unlikely(n > datalen - dp))
+ goto data_overrun_error;
+ len = 0;
+ for (; n > 0; n--) {
+ len <<= 8;
+ len |= data[dp++];
+ }
+check_length:
+ if (len > datalen - dp)
+ goto data_overrun_error;
+ dp += len;
+ goto next_tag;
+
+length_too_long:
+ *_errmsg = "Unsupported length";
+ goto error;
+indefinite_len_primitive:
+ *_errmsg = "Indefinite len primitive not permitted";
+ goto error;
+invalid_eoc:
+ *_errmsg = "Invalid length EOC";
+ goto error;
+data_overrun_error:
+ *_errmsg = "Data overrun error";
+ goto error;
+missing_eoc:
+ *_errmsg = "Missing EOC in indefinite len cons";
+error:
+ *_dp = dp;
+ return -1;
+}
+
+/**
+ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern
+ * @decoder: The decoder definition (produced by asn1_compiler)
+ * @context: The caller's context (to be passed to the action functions)
+ * @data: The encoded data
+ * @datalen: The size of the encoded data
+ *
+ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern
+ * produced by asn1_compiler. Action functions are called on marked tags to
+ * allow the caller to retrieve significant data.
+ *
+ * LIMITATIONS:
+ *
+ * To keep down the amount of stack used by this function, the following limits
+ * have been imposed:
+ *
+ * (1) This won't handle datalen > 65535 without increasing the size of the
+ * cons stack elements and length_too_long checking.
+ *
+ * (2) The stack of constructed types is 10 deep. If the depth of non-leaf
+ * constructed types exceeds this, the decode will fail.
+ *
+ * (3) The SET type (not the SET OF type) isn't really supported as tracking
+ * what members of the set have been seen is a pain.
+ */
+int asn1_ber_decoder(const struct asn1_decoder *decoder,
+ void *context,
+ const unsigned char *data,
+ size_t datalen)
+{
+ const unsigned char *machine = decoder->machine;
+ const asn1_action_t *actions = decoder->actions;
+ size_t machlen = decoder->machlen;
+ enum asn1_opcode op;
+ unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0;
+ const char *errmsg;
+ size_t pc = 0, dp = 0, tdp = 0, len = 0;
+ int ret;
+
+ unsigned char flags = 0;
+#define FLAG_INDEFINITE_LENGTH 0x01
+#define FLAG_MATCHED 0x02
+#define FLAG_LAST_MATCHED 0x04 /* Last tag matched */
+#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag
+ * - ie. whether or not we are going to parse
+ * a compound type.
+ */
+
+#define NR_CONS_STACK 10
+ unsigned short cons_dp_stack[NR_CONS_STACK];
+ unsigned short cons_datalen_stack[NR_CONS_STACK];
+ unsigned char cons_hdrlen_stack[NR_CONS_STACK];
+#define NR_JUMP_STACK 10
+ unsigned char jump_stack[NR_JUMP_STACK];
+
+ if (datalen > 65535)
+ return -EMSGSIZE;
+
+next_op:
+ pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n",
+ pc, machlen, dp, datalen, csp, jsp);
+ if (unlikely(pc >= machlen))
+ goto machine_overrun_error;
+ op = machine[pc];
+ if (unlikely(pc + asn1_op_lengths[op] > machlen))
+ goto machine_overrun_error;
+
+ /* If this command is meant to match a tag, then do that before
+ * evaluating the command.
+ */
+ if (op <= ASN1_OP__MATCHES_TAG) {
+ unsigned char tmp;
+
+ /* Skip conditional matches if possible */
+ if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
+ (op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
+ flags &= ~FLAG_LAST_MATCHED;
+ pc += asn1_op_lengths[op];
+ goto next_op;
+ }
+
+ flags = 0;
+ hdr = 2;
+
+ /* Extract a tag from the data */
+ if (unlikely(datalen - dp < 2))
+ goto data_overrun_error;
+ tag = data[dp++];
+ if (unlikely((tag & 0x1f) == ASN1_LONG_TAG))
+ goto long_tag_not_supported;
+
+ if (op & ASN1_OP_MATCH__ANY) {
+ pr_debug("- any %02x\n", tag);
+ } else {
+ /* Extract the tag from the machine
+ * - Either CONS or PRIM are permitted in the data if
+ * CONS is not set in the op stream, otherwise CONS
+ * is mandatory.
+ */
+ optag = machine[pc + 1];
+ flags |= optag & FLAG_CONS;
+
+ /* Determine whether the tag matched */
+ tmp = optag ^ tag;
+ tmp &= ~(optag & ASN1_CONS_BIT);
+ pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp);
+ if (tmp != 0) {
+ /* All odd-numbered tags are MATCH_OR_SKIP. */
+ if (op & ASN1_OP_MATCH__SKIP) {
+ pc += asn1_op_lengths[op];
+ dp--;
+ goto next_op;
+ }
+ goto tag_mismatch;
+ }
+ }
+ flags |= FLAG_MATCHED;
+
+ len = data[dp++];
+ if (len > 0x7f) {
+ if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
+ /* Indefinite length */
+ if (unlikely(!(tag & ASN1_CONS_BIT)))
+ goto indefinite_len_primitive;
+ flags |= FLAG_INDEFINITE_LENGTH;
+ if (unlikely(2 > datalen - dp))
+ goto data_overrun_error;
+ } else {
+ int n = len - 0x80;
+ if (unlikely(n > 2))
+ goto length_too_long;
+ if (unlikely(n > datalen - dp))
+ goto data_overrun_error;
+ hdr += n;
+ for (len = 0; n > 0; n--) {
+ len <<= 8;
+ len |= data[dp++];
+ }
+ if (unlikely(len > datalen - dp))
+ goto data_overrun_error;
+ }
+ } else {
+ if (unlikely(len > datalen - dp))
+ goto data_overrun_error;
+ }
+
+ if (flags & FLAG_CONS) {
+ /* For expected compound forms, we stack the positions
+ * of the start and end of the data.
+ */
+ if (unlikely(csp >= NR_CONS_STACK))
+ goto cons_stack_overflow;
+ cons_dp_stack[csp] = dp;
+ cons_hdrlen_stack[csp] = hdr;
+ if (!(flags & FLAG_INDEFINITE_LENGTH)) {
+ cons_datalen_stack[csp] = datalen;
+ datalen = dp + len;
+ } else {
+ cons_datalen_stack[csp] = 0;
+ }
+ csp++;
+ }
+
+ pr_debug("- TAG: %02x %zu%s\n",
+ tag, len, flags & FLAG_CONS ? " CONS" : "");
+ tdp = dp;
+ }
+
+ /* Decide how to handle the operation */
+ switch (op) {
+ case ASN1_OP_MATCH:
+ case ASN1_OP_MATCH_OR_SKIP:
+ case ASN1_OP_MATCH_ACT:
+ case ASN1_OP_MATCH_ACT_OR_SKIP:
+ case ASN1_OP_MATCH_ANY:
+ case ASN1_OP_MATCH_ANY_OR_SKIP:
+ case ASN1_OP_MATCH_ANY_ACT:
+ case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
+ case ASN1_OP_COND_MATCH_OR_SKIP:
+ case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
+ case ASN1_OP_COND_MATCH_ANY:
+ case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
+ case ASN1_OP_COND_MATCH_ANY_ACT:
+ case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
+
+ if (!(flags & FLAG_CONS)) {
+ if (flags & FLAG_INDEFINITE_LENGTH) {
+ size_t tmp = dp;
+
+ ret = asn1_find_indefinite_length(
+ data, datalen, &tmp, &len, &errmsg);
+ if (ret < 0)
+ goto error;
+ }
+ pr_debug("- LEAF: %zu\n", len);
+ }
+
+ if (op & ASN1_OP_MATCH__ACT) {
+ unsigned char act;
+
+ if (op & ASN1_OP_MATCH__ANY)
+ act = machine[pc + 1];
+ else
+ act = machine[pc + 2];
+ ret = actions[act](context, hdr, tag, data + dp, len);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!(flags & FLAG_CONS))
+ dp += len;
+ pc += asn1_op_lengths[op];
+ goto next_op;
+
+ case ASN1_OP_MATCH_JUMP:
+ case ASN1_OP_MATCH_JUMP_OR_SKIP:
+ case ASN1_OP_COND_MATCH_JUMP_OR_SKIP:
+ pr_debug("- MATCH_JUMP\n");
+ if (unlikely(jsp == NR_JUMP_STACK))
+ goto jump_stack_overflow;
+ jump_stack[jsp++] = pc + asn1_op_lengths[op];
+ pc = machine[pc + 2];
+ goto next_op;
+
+ case ASN1_OP_COND_FAIL:
+ if (unlikely(!(flags & FLAG_MATCHED)))
+ goto tag_mismatch;
+ pc += asn1_op_lengths[op];
+ goto next_op;
+
+ case ASN1_OP_COMPLETE:
+ if (unlikely(jsp != 0 || csp != 0)) {
+ pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n",
+ jsp, csp);
+ return -EBADMSG;
+ }
+ return 0;
+
+ case ASN1_OP_END_SET:
+ case ASN1_OP_END_SET_ACT:
+ if (unlikely(!(flags & FLAG_MATCHED)))
+ goto tag_mismatch;
+ /* fall through */
+
+ case ASN1_OP_END_SEQ:
+ case ASN1_OP_END_SET_OF:
+ case ASN1_OP_END_SEQ_OF:
+ case ASN1_OP_END_SEQ_ACT:
+ case ASN1_OP_END_SET_OF_ACT:
+ case ASN1_OP_END_SEQ_OF_ACT:
+ if (unlikely(csp <= 0))
+ goto cons_stack_underflow;
+ csp--;
+ tdp = cons_dp_stack[csp];
+ hdr = cons_hdrlen_stack[csp];
+ len = datalen;
+ datalen = cons_datalen_stack[csp];
+ pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n",
+ tdp, dp, len, datalen);
+ if (datalen == 0) {
+ /* Indefinite length - check for the EOC. */
+ datalen = len;
+ if (unlikely(datalen - dp < 2))
+ goto data_overrun_error;
+ if (data[dp++] != 0) {
+ if (op & ASN1_OP_END__OF) {
+ dp--;
+ csp++;
+ pc = machine[pc + 1];
+ pr_debug("- continue\n");
+ goto next_op;
+ }
+ goto missing_eoc;
+ }
+ if (data[dp++] != 0)
+ goto invalid_eoc;
+ len = dp - tdp - 2;
+ } else {
+ if (dp < len && (op & ASN1_OP_END__OF)) {
+ datalen = len;
+ csp++;
+ pc = machine[pc + 1];
+ pr_debug("- continue\n");
+ goto next_op;
+ }
+ if (dp != len)
+ goto cons_length_error;
+ len -= tdp;
+ pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp);
+ }
+
+ if (op & ASN1_OP_END__ACT) {
+ unsigned char act;
+ if (op & ASN1_OP_END__OF)
+ act = machine[pc + 2];
+ else
+ act = machine[pc + 1];
+ ret = actions[act](context, hdr, 0, data + tdp, len);
+ if (ret < 0)
+ return ret;
+ }
+ pc += asn1_op_lengths[op];
+ goto next_op;
+
+ case ASN1_OP_MAYBE_ACT:
+ if (!(flags & FLAG_LAST_MATCHED)) {
+ pc += asn1_op_lengths[op];
+ goto next_op;
+ }
+ /* fall through */
+
+ case ASN1_OP_ACT:
+ ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
+ if (ret < 0)
+ return ret;
+ pc += asn1_op_lengths[op];
+ goto next_op;
+
+ case ASN1_OP_RETURN:
+ if (unlikely(jsp <= 0))
+ goto jump_stack_underflow;
+ pc = jump_stack[--jsp];
+ flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
+ goto next_op;
+
+ default:
+ break;
+ }
+
+ /* Shouldn't reach here */
+ pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
+ op, pc);
+ return -EBADMSG;
+
+data_overrun_error:
+ errmsg = "Data overrun error";
+ goto error;
+machine_overrun_error:
+ errmsg = "Machine overrun error";
+ goto error;
+jump_stack_underflow:
+ errmsg = "Jump stack underflow";
+ goto error;
+jump_stack_overflow:
+ errmsg = "Jump stack overflow";
+ goto error;
+cons_stack_underflow:
+ errmsg = "Cons stack underflow";
+ goto error;
+cons_stack_overflow:
+ errmsg = "Cons stack overflow";
+ goto error;
+cons_length_error:
+ errmsg = "Cons length error";
+ goto error;
+missing_eoc:
+ errmsg = "Missing EOC in indefinite len cons";
+ goto error;
+invalid_eoc:
+ errmsg = "Invalid length EOC";
+ goto error;
+length_too_long:
+ errmsg = "Unsupported length";
+ goto error;
+indefinite_len_primitive:
+ errmsg = "Indefinite len primitive not permitted";
+ goto error;
+tag_mismatch:
+ errmsg = "Unexpected tag";
+ goto error;
+long_tag_not_supported:
+ errmsg = "Long tag not supported";
+error:
+ pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n",
+ errmsg, pc, dp, optag, tag, len);
+ return -EBADMSG;
+}
+EXPORT_SYMBOL_GPL(asn1_ber_decoder);
+
+MODULE_LICENSE("GPL");
diff --git a/lib/at91/Makefile b/lib/at91/Makefile
new file mode 100644
index 00000000..f8d0b9d4
--- /dev/null
+++ b/lib/at91/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2017 Microchip
+# Wenyou.Yang <wenyou.yang@microchip.com>
+
+obj-$(CONFIG_ARCH_AT91) += at91.o
diff --git a/lib/at91/at91.c b/lib/at91/at91.c
new file mode 100644
index 00000000..04859769
--- /dev/null
+++ b/lib/at91/at91.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Microchip
+ * Wenyou.Yang <wenyou.yang@microchip.com>
+ */
+
+#include <common.h>
+#include <atmel_lcd.h>
+
+#include "atmel_logo_8bpp.h"
+#include "microchip_logo_8bpp.h"
+
+void atmel_logo_info(vidinfo_t *info)
+{
+ info->logo_width = ATMEL_LOGO_8BPP_WIDTH;
+ info->logo_height = ATMEL_LOGO_8BPP_HEIGHT;
+ info->logo_x_offset = ATMEL_LOGO_8BPP_X_OFFSET;
+ info->logo_y_offset = ATMEL_LOGO_8BPP_X_OFFSET;
+ info->logo_addr = (u_long)atmel_logo_8bpp;
+}
+
+void microchip_logo_info(vidinfo_t *info)
+{
+ info->logo_width = MICROCHIP_LOGO_8BPP_WIDTH;
+ info->logo_height = MICROCHIP_LOGO_8BPP_HEIGHT;
+ info->logo_x_offset = MICROCHIP_LOGO_8BPP_X_OFFSET;
+ info->logo_y_offset = MICROCHIP_LOGO_8BPP_X_OFFSET;
+ info->logo_addr = (u_long)microchip_logo_8bpp;
+}
diff --git a/lib/at91/atmel_logo_8bpp.h b/lib/at91/atmel_logo_8bpp.h
new file mode 100644
index 00000000..dff5047f
--- /dev/null
+++ b/lib/at91/atmel_logo_8bpp.h
@@ -0,0 +1,1309 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017 Microchip
+ * Wenyou.Yang <wenyou.yang@microchip.com>
+ */
+
+#ifndef __ATMEL_LOGO_8BPP_H__
+#define __ATMEL_LOGO_8BPP_H__
+
+#define ATMEL_LOGO_8BPP_WIDTH 240
+#define ATMEL_LOGO_8BPP_HEIGHT 60
+
+#define ATMEL_LOGO_8BPP_X_OFFSET 0
+#define ATMEL_LOGO_8BPP_Y_OFFSET 0
+
+/* Format: BMP 8BPP 240*60 */
+unsigned char atmel_logo_8bpp[] = {
+ 0x42, 0x4d, 0x76, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc4, 0x0e, 0x00, 0x00, 0xc4, 0x0e, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc1, 0x79, 0x00, 0xff, 0xc1, 0x7a,
+ 0x01, 0xff, 0xc2, 0x7a, 0x02, 0xff, 0xc2, 0x7b, 0x04, 0xff, 0xc2, 0x7c,
+ 0x05, 0xff, 0xc3, 0x7c, 0x06, 0xff, 0xc3, 0x7d, 0x08, 0xff, 0xc3, 0x7e,
+ 0x09, 0xff, 0xc4, 0x7e, 0x0a, 0xff, 0xc4, 0x7f, 0x0c, 0xff, 0xc4, 0x80,
+ 0x0d, 0xff, 0xc5, 0x81, 0x0f, 0xff, 0xc5, 0x81, 0x10, 0xff, 0xc5, 0x82,
+ 0x11, 0xff, 0xc6, 0x82, 0x12, 0xff, 0xc6, 0x83, 0x14, 0xff, 0xc6, 0x84,
+ 0x15, 0xff, 0xc7, 0x85, 0x17, 0xff, 0xc7, 0x85, 0x18, 0xff, 0xc7, 0x86,
+ 0x1a, 0xff, 0xc8, 0x87, 0x1b, 0xff, 0xc8, 0x87, 0x1c, 0xff, 0xc8, 0x88,
+ 0x1d, 0xff, 0xc9, 0x89, 0x1f, 0xff, 0xc9, 0x8a, 0x1f, 0xff, 0xc8, 0x89,
+ 0x20, 0xff, 0xc9, 0x8a, 0x21, 0xff, 0xca, 0x8b, 0x23, 0xff, 0xca, 0x8c,
+ 0x23, 0xff, 0xc9, 0x8c, 0x24, 0xff, 0xca, 0x8c, 0x25, 0xff, 0xca, 0x8e,
+ 0x28, 0xff, 0xcb, 0x8e, 0x29, 0xff, 0xcb, 0x90, 0x2b, 0xff, 0xcc, 0x90,
+ 0x2b, 0xff, 0xcb, 0x90, 0x2c, 0xff, 0xcc, 0x90, 0x2e, 0xff, 0xcc, 0x91,
+ 0x30, 0xff, 0xcc, 0x92, 0x30, 0xff, 0xcd, 0x92, 0x31, 0xff, 0xcd, 0x94,
+ 0x33, 0xff, 0xcd, 0x93, 0x34, 0xff, 0xcd, 0x94, 0x34, 0xff, 0xce, 0x94,
+ 0x35, 0xff, 0xce, 0x96, 0x37, 0xff, 0xce, 0x96, 0x38, 0xff, 0xcf, 0x97,
+ 0x39, 0xff, 0xcf, 0x98, 0x3d, 0xff, 0xd0, 0x99, 0x3d, 0xff, 0xd0, 0x9a,
+ 0x40, 0xff, 0xd1, 0x9b, 0x41, 0xff, 0xd1, 0x9c, 0x42, 0xff, 0xd1, 0x9c,
+ 0x44, 0xff, 0xd2, 0x9d, 0x46, 0xff, 0xd2, 0x9e, 0x47, 0xff, 0xd2, 0x9e,
+ 0x48, 0xff, 0xd3, 0x9f, 0x49, 0xff, 0xd3, 0xa0, 0x4a, 0xff, 0xd3, 0xa0,
+ 0x4c, 0xff, 0xd4, 0xa2, 0x4e, 0xff, 0xd4, 0xa2, 0x50, 0xff, 0xd5, 0xa4,
+ 0x52, 0xff, 0xd5, 0xa4, 0x55, 0xff, 0xd5, 0xa6, 0x56, 0xff, 0xd6, 0xa6,
+ 0x57, 0xff, 0xd6, 0xa6, 0x58, 0xff, 0xd7, 0xa8, 0x5a, 0xff, 0xd7, 0xa8,
+ 0x5c, 0xff, 0xd7, 0xaa, 0x5d, 0xff, 0xd8, 0xaa, 0x5e, 0xff, 0xd8, 0xab,
+ 0x60, 0xff, 0xd8, 0xac, 0x61, 0xff, 0xd9, 0xad, 0x63, 0xff, 0xd9, 0xad,
+ 0x64, 0xff, 0xd9, 0xae, 0x65, 0xff, 0xda, 0xae, 0x66, 0xff, 0xda, 0xaf,
+ 0x68, 0xff, 0xda, 0xb0, 0x69, 0xff, 0xdb, 0xb0, 0x6b, 0xff, 0xdb, 0xb1,
+ 0x6c, 0xff, 0xdb, 0xb2, 0x6d, 0xff, 0xdc, 0xb3, 0x6f, 0xff, 0xdc, 0xb3,
+ 0x70, 0xff, 0xdc, 0xb4, 0x71, 0xff, 0xdd, 0xb5, 0x73, 0xff, 0xdd, 0xb5,
+ 0x74, 0xff, 0xdd, 0xb6, 0x75, 0xff, 0xde, 0xb7, 0x77, 0xff, 0xde, 0xb7,
+ 0x78, 0xff, 0xde, 0xb8, 0x79, 0xff, 0xdf, 0xb9, 0x7a, 0xff, 0xdf, 0xb9,
+ 0x7c, 0xff, 0xdf, 0xba, 0x7d, 0xff, 0xe0, 0xbb, 0x7f, 0xff, 0xdf, 0xbb,
+ 0x80, 0xff, 0xe0, 0xbc, 0x81, 0xff, 0xe1, 0xbd, 0x83, 0xff, 0xe1, 0xbe,
+ 0x83, 0xff, 0xe0, 0xbe, 0x84, 0xff, 0xe1, 0xbe, 0x84, 0xff, 0xe1, 0xc0,
+ 0x87, 0xff, 0xe2, 0xc0, 0x87, 0xff, 0xe1, 0xc0, 0x88, 0xff, 0xe2, 0xc0,
+ 0x89, 0xff, 0xe3, 0xc2, 0x8b, 0xff, 0xe2, 0xc2, 0x8c, 0xff, 0xe3, 0xc2,
+ 0x8c, 0xff, 0xe3, 0xc3, 0x90, 0xff, 0xe3, 0xc4, 0x90, 0xff, 0xe4, 0xc4,
+ 0x90, 0xff, 0xe4, 0xc6, 0x93, 0xff, 0xe5, 0xc6, 0x93, 0xff, 0xe4, 0xc6,
+ 0x94, 0xff, 0xe5, 0xc6, 0x94, 0xff, 0xe5, 0xc8, 0x97, 0xff, 0xe5, 0xc8,
+ 0x98, 0xff, 0xe6, 0xc8, 0x98, 0xff, 0xe6, 0xca, 0x9a, 0xff, 0xe6, 0xcb,
+ 0x9c, 0xff, 0xe7, 0xcb, 0x9d, 0xff, 0xe7, 0xcc, 0xa0, 0xff, 0xe8, 0xcd,
+ 0xa1, 0xff, 0xe8, 0xce, 0xa2, 0xff, 0xe8, 0xcf, 0xa4, 0xff, 0xe9, 0xcf,
+ 0xa5, 0xff, 0xe9, 0xd0, 0xa6, 0xff, 0xe9, 0xd1, 0xa8, 0xff, 0xea, 0xd1,
+ 0xa9, 0xff, 0xea, 0xd2, 0xaa, 0xff, 0xea, 0xd3, 0xac, 0xff, 0xeb, 0xd3,
+ 0xae, 0xff, 0xeb, 0xd4, 0xae, 0xff, 0xeb, 0xd5, 0xb0, 0xff, 0xeb, 0xd6,
+ 0xb0, 0xff, 0xec, 0xd5, 0xb1, 0xff, 0xec, 0xd6, 0xb1, 0xff, 0xec, 0xd7,
+ 0xb4, 0xff, 0xec, 0xd8, 0xb5, 0xff, 0xed, 0xd8, 0xb6, 0xff, 0xed, 0xd9,
+ 0xb8, 0xff, 0xed, 0xda, 0xb9, 0xff, 0xee, 0xda, 0xba, 0xff, 0xee, 0xdb,
+ 0xbc, 0xff, 0xee, 0xdc, 0xbc, 0xff, 0xef, 0xdc, 0xbe, 0xff, 0xef, 0xdd,
+ 0xc0, 0xff, 0xef, 0xde, 0xc0, 0xff, 0xf0, 0xde, 0xc2, 0xff, 0xf0, 0xe0,
+ 0xc5, 0xff, 0xf1, 0xe0, 0xc6, 0xff, 0xf1, 0xe1, 0xc8, 0xff, 0xf1, 0xe2,
+ 0xc8, 0xff, 0xf2, 0xe3, 0xca, 0xff, 0xf2, 0xe4, 0xcd, 0xff, 0xf3, 0xe5,
+ 0xce, 0xff, 0xf3, 0xe6, 0xd1, 0xff, 0xf4, 0xe7, 0xd3, 0xff, 0xf4, 0xe8,
+ 0xd3, 0xff, 0xf4, 0xe8, 0xd4, 0xff, 0xf5, 0xea, 0xd7, 0xff, 0xf5, 0xea,
+ 0xd9, 0xff, 0xf6, 0xeb, 0xdb, 0xff, 0xf6, 0xec, 0xdb, 0xff, 0xf6, 0xec,
+ 0xdd, 0xff, 0xf6, 0xee, 0xdf, 0xff, 0xf7, 0xee, 0xdf, 0xff, 0xf7, 0xee,
+ 0xe1, 0xff, 0xf8, 0xf0, 0xe3, 0xff, 0xf8, 0xf0, 0xe4, 0xff, 0xf8, 0xf2,
+ 0xe6, 0xff, 0xf9, 0xf2, 0xe6, 0xff, 0xf9, 0xf2, 0xe8, 0xff, 0xf9, 0xf4,
+ 0xea, 0xff, 0xfa, 0xf4, 0xeb, 0xff, 0xfa, 0xf4, 0xec, 0xff, 0xfa, 0xf6,
+ 0xee, 0xff, 0xfb, 0xf6, 0xef, 0xff, 0xfb, 0xf7, 0xf0, 0xff, 0xfb, 0xf8,
+ 0xf2, 0xff, 0xfc, 0xf9, 0xf4, 0xff, 0xfc, 0xfa, 0xf6, 0xff, 0xfc, 0xfa,
+ 0xf8, 0xff, 0xfd, 0xfb, 0xf8, 0xff, 0xfd, 0xfc, 0xfa, 0xff, 0xfd, 0xfd,
+ 0xfc, 0xff, 0xfe, 0xfd, 0xfc, 0xff, 0xfe, 0xfe, 0xfd, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xa6, 0xa3,
+ 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xb0, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb6, 0xa6, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xab, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb3,
+ 0xa8, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0xb6, 0xba, 0xba, 0xba, 0xba,
+ 0xb8, 0xa8, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xb7, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xaf, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
+ 0xa3, 0xae, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0xa6, 0xa3, 0xa3, 0xa3,
+ 0xa3, 0xa3, 0xa3, 0xa3, 0xa6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xae, 0x97, 0x7a, 0x59, 0x3a, 0x27, 0x15, 0x0e, 0x0e, 0x0e, 0x19, 0x2b,
+ 0x3f, 0x5c, 0x80, 0x99, 0xb1, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb9, 0xaf, 0xa3, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x66, 0x2a,
+ 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x4f, 0xae, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xa1, 0x37, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x5a, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xb4, 0x90, 0x5b, 0x39,
+ 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x24, 0xa7, 0xba, 0xba, 0xba, 0xba,
+ 0xb1, 0x44, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2c, 0xa8, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0x7a, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+ 0x27, 0x74, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x9a, 0x36, 0x27, 0x27, 0x27,
+ 0x27, 0x27, 0x27, 0x27, 0x40, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xa6, 0x6d,
+ 0x31, 0x16, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x1a, 0x37, 0x71, 0xa9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0xab,
+ 0x7a, 0x4a, 0x33, 0x27, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa8, 0x3c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xb3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x9e, 0x5d, 0x1a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x98, 0x53, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x52, 0x99, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x8a, 0x41, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xa0,
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x71, 0xb6,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb2, 0x6a, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb1, 0x74, 0x1b, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x6e, 0xb1, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xa0, 0x46, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0x92, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x7c,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0x94, 0x31, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xa3, 0x3a, 0x02, 0x00, 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, 0x35, 0x9e,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb3, 0x72, 0x12, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0xb7, 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+ 0x94, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb7, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0x9c, 0x35, 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, 0x2f,
+ 0x97, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0xba, 0xb7, 0x65, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x9e, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0x7e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xa0, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x16, 0x99, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xaf, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0xba, 0xba, 0xaf, 0x4d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3b, 0xab, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9,
+ 0x92, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xa8, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x27, 0x3e, 0x4d, 0x4d, 0x3c, 0x20,
+ 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x34, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb4, 0x5f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x46, 0xb1, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa3,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb9, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x13, 0x42, 0x80, 0xa8, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7,
+ 0x9e, 0x6a, 0x31, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x42, 0xb8, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0x9e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x63, 0xb6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x52,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x11, 0x2b, 0x39, 0x3b, 0x3b, 0x3b, 0x3d, 0xab, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0x8f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x3a, 0x97, 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb9, 0xa8, 0x72, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x8d, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xa0, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x0d, 0x16, 0x31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0x98, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x75, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x8d, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3c, 0x80,
+ 0xaa, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xac, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x73, 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0x9e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x37, 0xac, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb6, 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1a, 0x54, 0x94, 0xb3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb8, 0x7d, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0x8f, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x43, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x17, 0x7d, 0xae, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x84, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x75,
+ 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0x9f, 0x35, 0x09, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x16, 0x90, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xa0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3a,
+ 0x99, 0xb5, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb8, 0x70, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x99, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x9b, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x95, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7,
+ 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xb6,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa2, 0x7d, 0x7b, 0x7b, 0x7b, 0x7b,
+ 0x7b, 0x7b, 0x7b, 0x7b, 0xa0, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xad,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x53, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0xa6, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x5f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x8e, 0xb9, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x9a,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xb4, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xab,
+ 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36, 0xa8, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xae, 0x41, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0xad, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x56, 0xb6, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0x67,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x84, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x8e,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x90, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa3, 0x30, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x55, 0xb3, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x9e, 0x1a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x9b, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xaf, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xa9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6e,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xb7, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x98, 0x1e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x72, 0xb7, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x8a, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa3, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb6, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0x8a,
+ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x7d, 0xb9,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x79, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x97, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xa0, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb6,
+ 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x95,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xb1, 0xb8, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x71, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x33,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb6, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+ 0x13, 0x13, 0x13, 0x13, 0x28, 0xa6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x67, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x24, 0x24, 0x4d, 0xb2, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xae, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xb1, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xaa, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 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, 0x39, 0xb1, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0x99, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x47, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xb1, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x91, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x47, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xb2, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x4e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xb4, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0x69, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa3, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x93, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xb9, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x46, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xaf, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5c, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x92, 0x13, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba, 0x7a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa9, 0x3e, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x7d, 0xb1, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb2, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb6, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x44, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x83, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2f, 0xba, 0xba, 0xba, 0xba, 0xba, 0x97, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0x91, 0x16, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x7d, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa0, 0x1e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x63, 0xb4, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb2, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x27, 0xb3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0x62, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3d, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa3, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xb1, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x8a, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x9b, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x97, 0x1e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x67, 0xb9, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb8, 0x5f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xad,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0d, 0x85, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x22, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x43,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x8d, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x46, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x15, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x80, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x8d, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0x7d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x7a,
+ 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x44, 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x87, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6e,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4a, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa6, 0x16, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6d,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x90, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xa0, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d,
+ 0x9e, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb8, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x75, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0x99, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0xa3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa6,
+ 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb3, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x87, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb1,
+ 0x50, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xa8,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb7, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3b, 0xa6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb9, 0x90, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x89, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xae, 0x31, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x9f,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0x8b, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2b, 0xa6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb5, 0x3b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
+ 0xa7, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x8e, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x27, 0x90, 0xb6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xae,
+ 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0xad, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb7, 0x88, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x99, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a,
+ 0xa0, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb7, 0x93, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6f, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0x9e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x4d, 0xb6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb2, 0xb2, 0xb2, 0xb2, 0x67, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+ 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xae, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x4c, 0x98, 0xb1, 0xb4, 0xb4, 0xb3, 0xae, 0x78, 0x37,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x35, 0x80, 0xab, 0xb3, 0xb4, 0xb3,
+ 0xb2, 0x92, 0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x31, 0xb3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb4, 0x56, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2e, 0x8b, 0xb6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb5, 0x80, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x17, 0xae, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x9f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x5f, 0xb3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 0x23, 0x0d, 0x0d, 0x0d, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x24, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0x8b, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x13, 0x2f, 0x34, 0x26, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x27, 0x33, 0x2e,
+ 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0d, 0x8e, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xab, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x45, 0x83, 0xa8, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9,
+ 0xa8, 0x83, 0x3d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0a, 0x78, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0x7e, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0d, 0x7c, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb4, 0x4e, 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,
+ 0x03, 0x52, 0xb3, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x86, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0d, 0x28, 0x40, 0x5f, 0x71, 0x7c, 0x72, 0x5f, 0x41,
+ 0x27, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x43, 0xaf, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb7, 0x79, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x8e, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xaa, 0x31, 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, 0x04, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x32, 0xae, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb7, 0x77, 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,
+ 0x27, 0xa9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb6, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x26, 0x9b, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb9, 0x98, 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, 0x07, 0x56, 0x48, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2b,
+ 0x98, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb4, 0x5f, 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, 0x23,
+ 0x92, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xae, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0xa6, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x97, 0x26, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x56, 0xb4, 0xb1, 0x4c, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x9e,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xb4, 0x73, 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, 0x24, 0x98,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa8, 0x2e, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x46, 0xac, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb8, 0x9b, 0x33, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x6a, 0xb1, 0xba, 0xba, 0xaf, 0x5c,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3b, 0x9b, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x7f, 0x24, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x39, 0x99, 0xb9,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x9a, 0x25, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, 0xb4, 0xba, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xac, 0x5e, 0x13, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x32, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb6,
+ 0x84, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x5f, 0xb2, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa5, 0x4a, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x5f, 0xb1, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0x90, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x71, 0xb6, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb1, 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, 0x16, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0x95, 0x43,
+ 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x21, 0x67, 0xa9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb9, 0xa3, 0x67, 0x1e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x47, 0x9b, 0xb5, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x94, 0x3c, 0x13,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x16, 0x4b, 0x9b, 0xb6, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb8, 0x76, 0x0d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x83, 0xba, 0xba, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb2, 0x3b, 0x2e, 0x2e, 0x2e, 0x1a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9,
+ 0x98, 0x63, 0x35, 0x13, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1e,
+ 0x44, 0x75, 0xab, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xa7, 0x75, 0x41, 0x1e, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x12, 0x3a, 0x5f, 0x9e, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x9a,
+ 0x5f, 0x38, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x12, 0x3a, 0x67, 0x9e, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb4, 0x61, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x94, 0xb9, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb9, 0xab, 0xa9, 0xa9, 0xa9, 0x5f, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
+ 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xb8, 0xac, 0xa2, 0x93, 0x7d, 0x6d, 0x6c, 0x74, 0x83, 0x9b, 0xa6,
+ 0xb2, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xb1, 0xa6, 0x99, 0x83, 0x72, 0x6c, 0x6e,
+ 0x7c, 0x94, 0xa0, 0xae, 0xb7, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb7, 0xae, 0xa0, 0x8b, 0x67, 0x4e, 0x3d, 0x37, 0x37, 0x37, 0x3d, 0x4e,
+ 0x6a, 0x8d, 0xa0, 0xae, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb3, 0x45,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xa3, 0xba,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa8,
+ 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0xa9,
+ 0x9b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xa0, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x4c,
+ 0x96, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xb9, 0x90, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x44, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x7d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb5, 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xb2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xab, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb7, 0x9e, 0x58, 0x40, 0x44, 0x6a, 0xab, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xa0, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x99, 0x37, 0x74, 0x98, 0x92, 0x59, 0x49, 0xab, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x99, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x44, 0x7d, 0x85, 0x9e, 0x94, 0x7d, 0x55, 0x71, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb7, 0x81, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xaf, 0x36, 0xa8, 0x62, 0x5f, 0x41, 0x95, 0x8d, 0x49, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0x72, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xae, 0x38, 0xac, 0x64, 0x71, 0x5c, 0x78, 0x90, 0x48, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x52, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xb9, 0x3e, 0x8e, 0x6b, 0x50, 0x53, 0x90, 0x65, 0x63, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb3, 0x43, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0x8f, 0x37, 0x88, 0xa3, 0x9e, 0x74, 0x3d, 0xa3, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xa0, 0x2e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0x6c, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb2, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xa8, 0xba, 0xba, 0xba,
+ 0xba, 0xba, 0xb6, 0x8f, 0x3f, 0x31, 0x34, 0x4c, 0xa0, 0xba
+};
+#endif
diff --git a/lib/at91/microchip_logo_8bpp.h b/lib/at91/microchip_logo_8bpp.h
new file mode 100644
index 00000000..a56f1607
--- /dev/null
+++ b/lib/at91/microchip_logo_8bpp.h
@@ -0,0 +1,1081 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017 Microchip
+ * Wenyou.Yang <wenyou.yang@microchip.com>
+ */
+
+#ifndef __MICROCHIP_LOGO_8BPP_H__
+#define __MICROCHIP_LOGO_8BPP_H__
+
+#define MICROCHIP_LOGO_8BPP_WIDTH 208
+#define MICROCHIP_LOGO_8BPP_HEIGHT 56
+
+#define MICROCHIP_LOGO_8BPP_X_OFFSET 0
+#define MCIROCHIP_LOGO_8BPP_Y_OFFSET 0
+
+/* Format: BMP 8BPP 240*60 */
+unsigned char microchip_logo_8bpp[] = {
+ 0x42, 0x4d, 0xb6, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x38, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2d,
+ 0x00, 0x00, 0x74, 0x12, 0x00, 0x00, 0x74, 0x12, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0xc0, 0xc0,
+ 0xc0, 0x00, 0xc0, 0xdc, 0xc0, 0x00, 0xf0, 0xca, 0xa6, 0x00, 0x00, 0x20,
+ 0x40, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20,
+ 0xa0, 0x00, 0x00, 0x20, 0xc0, 0x00, 0x00, 0x20, 0xe0, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40,
+ 0x60, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40,
+ 0xc0, 0x00, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60,
+ 0x20, 0x00, 0x00, 0x60, 0x40, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x60,
+ 0x80, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x60, 0xc0, 0x00, 0x00, 0x60,
+ 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80,
+ 0x40, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
+ 0xa0, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x80, 0xe0, 0x00, 0x00, 0xa0,
+ 0x00, 0x00, 0x00, 0xa0, 0x20, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xa0,
+ 0x60, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0xa0, 0xa0, 0x00, 0x00, 0xa0,
+ 0xc0, 0x00, 0x00, 0xa0, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0,
+ 0x20, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0,
+ 0x80, 0x00, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xc0,
+ 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0xe0,
+ 0x40, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0,
+ 0xa0, 0x00, 0x00, 0xe0, 0xc0, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+ 0x60, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xa0, 0x00, 0x40, 0x00,
+ 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20,
+ 0x20, 0x00, 0x40, 0x20, 0x40, 0x00, 0x40, 0x20, 0x60, 0x00, 0x40, 0x20,
+ 0x80, 0x00, 0x40, 0x20, 0xa0, 0x00, 0x40, 0x20, 0xc0, 0x00, 0x40, 0x20,
+ 0xe0, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x40, 0x40,
+ 0x40, 0x00, 0x40, 0x40, 0x60, 0x00, 0x40, 0x40, 0x80, 0x00, 0x40, 0x40,
+ 0xa0, 0x00, 0x40, 0x40, 0xc0, 0x00, 0x40, 0x40, 0xe0, 0x00, 0x40, 0x60,
+ 0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0x40, 0x60, 0x40, 0x00, 0x40, 0x60,
+ 0x60, 0x00, 0x40, 0x60, 0x80, 0x00, 0x40, 0x60, 0xa0, 0x00, 0x40, 0x60,
+ 0xc0, 0x00, 0x40, 0x60, 0xe0, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0x80,
+ 0x20, 0x00, 0x40, 0x80, 0x40, 0x00, 0x40, 0x80, 0x60, 0x00, 0x40, 0x80,
+ 0x80, 0x00, 0x40, 0x80, 0xa0, 0x00, 0x40, 0x80, 0xc0, 0x00, 0x40, 0x80,
+ 0xe0, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, 0xa0, 0x20, 0x00, 0x40, 0xa0,
+ 0x40, 0x00, 0x40, 0xa0, 0x60, 0x00, 0x40, 0xa0, 0x80, 0x00, 0x40, 0xa0,
+ 0xa0, 0x00, 0x40, 0xa0, 0xc0, 0x00, 0x40, 0xa0, 0xe0, 0x00, 0x40, 0xc0,
+ 0x00, 0x00, 0x40, 0xc0, 0x20, 0x00, 0x40, 0xc0, 0x40, 0x00, 0x40, 0xc0,
+ 0x60, 0x00, 0x40, 0xc0, 0x80, 0x00, 0x40, 0xc0, 0xa0, 0x00, 0x40, 0xc0,
+ 0xc0, 0x00, 0x40, 0xc0, 0xe0, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x40, 0xe0,
+ 0x20, 0x00, 0x40, 0xe0, 0x40, 0x00, 0x40, 0xe0, 0x60, 0x00, 0x40, 0xe0,
+ 0x80, 0x00, 0x40, 0xe0, 0xa0, 0x00, 0x40, 0xe0, 0xc0, 0x00, 0x40, 0xe0,
+ 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00,
+ 0x40, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
+ 0xa0, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x80, 0x20,
+ 0x00, 0x00, 0x80, 0x20, 0x20, 0x00, 0x80, 0x20, 0x40, 0x00, 0x80, 0x20,
+ 0x60, 0x00, 0x80, 0x20, 0x80, 0x00, 0x80, 0x20, 0xa0, 0x00, 0x80, 0x20,
+ 0xc0, 0x00, 0x80, 0x20, 0xe0, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40,
+ 0x20, 0x00, 0x80, 0x40, 0x40, 0x00, 0x80, 0x40, 0x60, 0x00, 0x80, 0x40,
+ 0x80, 0x00, 0x80, 0x40, 0xa0, 0x00, 0x80, 0x40, 0xc0, 0x00, 0x80, 0x40,
+ 0xe0, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x60, 0x20, 0x00, 0x80, 0x60,
+ 0x40, 0x00, 0x80, 0x60, 0x60, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60,
+ 0xa0, 0x00, 0x80, 0x60, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x00, 0x80, 0x80,
+ 0x00, 0x00, 0x80, 0x80, 0x20, 0x00, 0x80, 0x80, 0x40, 0x00, 0x80, 0x80,
+ 0x60, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0xa0, 0x00, 0x80, 0x80,
+ 0xc0, 0x00, 0x80, 0x80, 0xe0, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, 0xa0,
+ 0x20, 0x00, 0x80, 0xa0, 0x40, 0x00, 0x80, 0xa0, 0x60, 0x00, 0x80, 0xa0,
+ 0x80, 0x00, 0x80, 0xa0, 0xa0, 0x00, 0x80, 0xa0, 0xc0, 0x00, 0x80, 0xa0,
+ 0xe0, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x00, 0x80, 0xc0,
+ 0x40, 0x00, 0x80, 0xc0, 0x60, 0x00, 0x80, 0xc0, 0x80, 0x00, 0x80, 0xc0,
+ 0xa0, 0x00, 0x80, 0xc0, 0xc0, 0x00, 0x80, 0xc0, 0xe0, 0x00, 0x80, 0xe0,
+ 0x00, 0x00, 0x80, 0xe0, 0x20, 0x00, 0x80, 0xe0, 0x40, 0x00, 0x80, 0xe0,
+ 0x60, 0x00, 0x80, 0xe0, 0x80, 0x00, 0x80, 0xe0, 0xa0, 0x00, 0x80, 0xe0,
+ 0xc0, 0x00, 0x80, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00,
+ 0x20, 0x00, 0xc0, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xc0, 0x00,
+ 0x80, 0x00, 0xc0, 0x00, 0xa0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
+ 0xe0, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x20, 0x00, 0xc0, 0x20,
+ 0x40, 0x00, 0xc0, 0x20, 0x60, 0x00, 0xc0, 0x20, 0x80, 0x00, 0xc0, 0x20,
+ 0xa0, 0x00, 0xc0, 0x20, 0xc0, 0x00, 0xc0, 0x20, 0xe0, 0x00, 0xc0, 0x40,
+ 0x00, 0x00, 0xc0, 0x40, 0x20, 0x00, 0xc0, 0x40, 0x40, 0x00, 0xc0, 0x40,
+ 0x60, 0x00, 0xc0, 0x40, 0x80, 0x00, 0xc0, 0x40, 0xa0, 0x00, 0xc0, 0x40,
+ 0xc0, 0x00, 0xc0, 0x40, 0xe0, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x60,
+ 0x20, 0x00, 0xc0, 0x60, 0x40, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60,
+ 0x80, 0x00, 0xc0, 0x60, 0xa0, 0x00, 0xc0, 0x60, 0xc0, 0x00, 0xc0, 0x60,
+ 0xe0, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0x80, 0x20, 0x00, 0xc0, 0x80,
+ 0x40, 0x00, 0xc0, 0x80, 0x60, 0x00, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0x80,
+ 0xa0, 0x00, 0xc0, 0x80, 0xc0, 0x00, 0xc0, 0x80, 0xe0, 0x00, 0xc0, 0xa0,
+ 0x00, 0x00, 0xc0, 0xa0, 0x20, 0x00, 0xc0, 0xa0, 0x40, 0x00, 0xc0, 0xa0,
+ 0x60, 0x00, 0xc0, 0xa0, 0x80, 0x00, 0xc0, 0xa0, 0xa0, 0x00, 0xc0, 0xa0,
+ 0xc0, 0x00, 0xc0, 0xa0, 0xe0, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0,
+ 0x20, 0x00, 0xc0, 0xc0, 0x40, 0x00, 0xc0, 0xc0, 0x60, 0x00, 0xc0, 0xc0,
+ 0x80, 0x00, 0xc0, 0xc0, 0xa0, 0x00, 0xf0, 0xfb, 0xff, 0x00, 0xa4, 0xa0,
+ 0xa0, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xef, 0xef,
+ 0xa7, 0x9f, 0x57, 0x57, 0x4f, 0x4f, 0x57, 0x57, 0x5f, 0xa7, 0xef, 0xef,
+ 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6,
+ 0xa7, 0x5f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x57, 0xa7, 0xef, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0xef, 0xa7, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x5f,
+ 0xef, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0xa7, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x9f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x57, 0xaf,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xaf, 0x57, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x9f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xa7, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xef, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0x0f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f,
+ 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x0f, 0x0f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f,
+ 0xa7, 0xef, 0x9f, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x0f, 0x0f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x9f, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x0f, 0x9f, 0xf6, 0xff, 0xf6, 0x9f, 0x0f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57, 0xef, 0xff, 0xff, 0xff, 0xf6,
+ 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57, 0xef,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f,
+ 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0xaf, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x0f, 0x0f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xa7, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x0f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x9f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f, 0x0f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x0f, 0x57, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57, 0xef, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xef, 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xa4, 0x5b, 0x5b, 0x5b, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf7, 0x5b, 0x5b, 0x5b, 0xa4, 0xff, 0xf6, 0x9b, 0x5b,
+ 0x5b, 0xa4, 0xf6, 0xff, 0xff, 0xf6, 0xf7, 0x5b, 0x52, 0x52, 0x52, 0x52,
+ 0x52, 0x52, 0x52, 0x52, 0x52, 0xa4, 0x08, 0xff, 0xf6, 0xa4, 0x5b, 0x5b,
+ 0xa4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf7, 0x5b, 0x5b, 0x9b,
+ 0x08, 0xff, 0xff, 0xf6, 0xf7, 0x5b, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
+ 0x52, 0x52, 0x5b, 0xa4, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xa4, 0x5b,
+ 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x9b, 0x08, 0xff,
+ 0xf6, 0xa4, 0x5b, 0x5b, 0xa4, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0xa4, 0x5b, 0x5b, 0x9b, 0xff, 0xf6, 0xa4, 0x5b, 0x5b, 0x5b, 0x07, 0xff,
+ 0xf7, 0x5b, 0x5b, 0x9b, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
+ 0x0f, 0x4f, 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x52,
+ 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xa4, 0x5b,
+ 0xa4, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x00, 0x00, 0x00, 0x52,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x49, 0x08, 0xff, 0xf6, 0x5b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xf6,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x52, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x49, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x0f,
+ 0x4f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xef, 0x57, 0x4f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0xef, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b,
+ 0x00, 0x00, 0x00, 0x9b, 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0x08, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x07, 0xff, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x5b, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa4, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf6, 0x52, 0x00, 0x00,
+ 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49,
+ 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00,
+ 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xf6, 0x57, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x5f, 0x0f, 0x4f, 0x0f, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f, 0x0f, 0x4f, 0x0f, 0xa7, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f, 0x0f,
+ 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x00, 0x00, 0x00, 0x9b,
+ 0xf6, 0xff, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x07, 0xff,
+ 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xa4, 0xff, 0x08, 0x00, 0x00,
+ 0x00, 0x52, 0x08, 0xff, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x52, 0x00, 0x00,
+ 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5b, 0x00, 0x00, 0x00,
+ 0x07, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0x52, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x4f, 0x0f, 0x57, 0xf6, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x0f, 0x4f,
+ 0x0f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xaf, 0x0f, 0x4f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b,
+ 0x00, 0x00, 0x00, 0x5b, 0xf6, 0xff, 0xff, 0xf6, 0x5b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0x08, 0xf6, 0x52, 0x00, 0x00, 0x00,
+ 0x49, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x52, 0x5b, 0x08,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xf7,
+ 0x49, 0x00, 0x00, 0x49, 0x08, 0xff, 0x52, 0x00, 0x00, 0x00, 0x00, 0x52,
+ 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x49, 0x00, 0x00, 0x00, 0x49, 0x08, 0xf6,
+ 0x49, 0x00, 0x00, 0x00, 0x49, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+ 0x5b, 0x5b, 0x52, 0xf6, 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xa4, 0x07, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0x07, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x0f,
+ 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f, 0x0f, 0x4f,
+ 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x57, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x08, 0xff, 0xff, 0xf6, 0x49,
+ 0x00, 0x00, 0x00, 0x07, 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0xf6, 0x07,
+ 0x49, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x49, 0x00,
+ 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49,
+ 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xf6,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xaf, 0x4f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xa7, 0x0f, 0x4f, 0x0f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x9f, 0x0f, 0x4f, 0x0f, 0xa7, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x9f, 0x0f, 0x4f, 0x4f,
+ 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x52,
+ 0xf6, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7,
+ 0xff, 0xff, 0xf6, 0x49, 0x00, 0x00, 0x00, 0x08, 0xff, 0x08, 0x00, 0x00,
+ 0x00, 0x52, 0xf6, 0x07, 0x49, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x07,
+ 0xff, 0x08, 0x49, 0x00, 0x00, 0x49, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x52, 0x00, 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x52,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x49, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+ 0x49, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x4f, 0x4f, 0x0f, 0x57, 0xf6, 0xff,
+ 0xff, 0xff, 0xff, 0xef, 0x57, 0x0f, 0x0f, 0x57, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x4f, 0x0f, 0x57,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+ 0x4f, 0x0f, 0x4f, 0x4f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
+ 0x00, 0x00, 0x00, 0x49, 0x08, 0xff, 0xf6, 0x49, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5b, 0xf6, 0xff, 0x08, 0x49, 0x00, 0x00, 0x00, 0xf6,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0xf6, 0x07, 0x49, 0x00, 0x00, 0x5b,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x07, 0xff, 0xf6, 0x49, 0x00, 0x00, 0x49, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x07, 0xf6,
+ 0x49, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x4f, 0x4f,
+ 0x4f, 0x0f, 0x9f, 0xf6, 0xff, 0xff, 0xf6, 0x5f, 0x0f, 0x4f, 0x0f, 0xaf,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x57,
+ 0x0f, 0x4f, 0x0f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x5f, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x07, 0x49, 0x00, 0x00, 0x00, 0x08, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0x00,
+ 0x00, 0x00, 0x49, 0xf6, 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0xf6, 0x07,
+ 0x49, 0x00, 0x00, 0x5b, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xf6, 0xf6, 0x49, 0x00,
+ 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x00,
+ 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x9b, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00,
+ 0x49, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x00, 0x00, 0x00, 0x00, 0x9b,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xaf, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0xaf, 0xff, 0xff, 0xaf, 0x0f,
+ 0x4f, 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xa7, 0x0f, 0x4f, 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x0f, 0x4f, 0x4f, 0x4f, 0xef,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x49, 0x00, 0x00, 0x00,
+ 0x07, 0xff, 0x5b, 0x00, 0x00, 0x00, 0x49, 0xa4, 0x49, 0x00, 0x00, 0x00,
+ 0xa4, 0xff, 0x07, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0x08, 0x00, 0x00,
+ 0x00, 0x52, 0xf6, 0x07, 0x49, 0x00, 0x00, 0x5b, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x52, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x52, 0x00, 0x00, 0x49,
+ 0x08, 0xf6, 0x49, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x5b,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0xf7, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xa4,
+ 0x00, 0x00, 0x00, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57,
+ 0xf6, 0xf6, 0x57, 0x0f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x0f, 0x0f, 0x57, 0xef, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x0f,
+ 0x4f, 0x4f, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08,
+ 0x52, 0x00, 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x00, 0x5b, 0xf6,
+ 0x52, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xf7, 0x00, 0x00, 0x00, 0x5b, 0xff,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0xf6, 0x07, 0x49, 0x00, 0x00, 0x5b,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x08, 0xf6, 0x49, 0x00, 0x00, 0x49, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x00, 0x00, 0x00, 0x07, 0xf6,
+ 0x49, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x08, 0x49, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x0f, 0x5f, 0x5f, 0x0f, 0x4f, 0x0f, 0xa7, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f, 0x0f, 0x4f,
+ 0x0f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x5f, 0x0f, 0x4f, 0x4f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x07, 0xf7, 0x00, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf7, 0x00,
+ 0x00, 0x00, 0x9b, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0xf6, 0x07,
+ 0x49, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x08, 0xf6, 0x49, 0x00,
+ 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0x00,
+ 0x00, 0x00, 0x07, 0xf6, 0x49, 0x00, 0x00, 0x49, 0xf6, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x49, 0xa4, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xa4, 0x49, 0x00, 0x00, 0x49,
+ 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00,
+ 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x49, 0x00, 0x00, 0x52,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xef, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0x0f,
+ 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xa7, 0x0f, 0x4f, 0x0f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xa7, 0x0f, 0x0f, 0x4f, 0x4f, 0xef, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00,
+ 0xf7, 0x52, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0x07, 0x49, 0x00, 0x00,
+ 0x00, 0xa4, 0x9b, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0x08, 0x00, 0x00,
+ 0x00, 0x52, 0xf6, 0x08, 0x49, 0x00, 0x00, 0x00, 0xa4, 0xf6, 0xf6, 0xf6,
+ 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xff, 0xf6, 0x52, 0x00, 0x00,
+ 0x52, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xff, 0x08, 0x52, 0x00, 0x00, 0x00,
+ 0x08, 0xff, 0x52, 0x00, 0x00, 0x00, 0x9b, 0xf6, 0xff, 0xf6, 0xf6, 0xf6,
+ 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf6, 0x49, 0x00, 0x00, 0x00,
+ 0xa4, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xff,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xa4,
+ 0x00, 0x00, 0x00, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xef, 0x57, 0x0f, 0x0f, 0x4f, 0xef, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x0f, 0x4f, 0x4f,
+ 0xa7, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x9b, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff,
+ 0xf6, 0x5b, 0x00, 0x00, 0x00, 0x49, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0x08, 0xf6, 0x52, 0x00, 0x00, 0x00,
+ 0x00, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x52, 0x08,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x49,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x52, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0x52, 0x52, 0x52, 0x52, 0x49, 0x00, 0x00, 0x00, 0x00, 0x49, 0x08, 0xf6,
+ 0x49, 0x00, 0x00, 0x00, 0x00, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0xf6, 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x49, 0x52, 0x52, 0x52,
+ 0x52, 0x52, 0x49, 0x00, 0x00, 0x00, 0x00, 0x9b, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x9f, 0x0f, 0x4f, 0x0f, 0xa7,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x5f,
+ 0x0f, 0x4f, 0x4f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0xff, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0x08, 0xff,
+ 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x08, 0xff, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x08, 0xff, 0x9b, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x52, 0xf6, 0xff, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6, 0x52, 0x00, 0x00,
+ 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49,
+ 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xef, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x9f,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x0f,
+ 0x0f, 0x4f, 0x0f, 0x9f, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xaf, 0x0f, 0x0f, 0x4f, 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5b, 0xff, 0xff, 0xff, 0xff, 0x08, 0x52, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x08, 0x00, 0x00,
+ 0x00, 0x52, 0x08, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xf6, 0x52, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b,
+ 0xf6, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf6,
+ 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0xf7, 0xff,
+ 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x57, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x0f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x0f, 0x4f, 0x4f, 0x9f, 0xf6,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x07, 0xff,
+ 0xff, 0x08, 0x00, 0x00, 0x00, 0x52, 0x08, 0xff, 0xff, 0xa4, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0xf6,
+ 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x07, 0xff, 0xff, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xf6, 0xff, 0xff,
+ 0xf6, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa4, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x49, 0xff, 0xf6, 0x52, 0x00,
+ 0x00, 0x00, 0xf7, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0xef, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x9f, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f,
+ 0x4f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x9f, 0x0f, 0x4f,
+ 0x4f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x49, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x49, 0xf6, 0xff, 0xff, 0xf6, 0xa4, 0xa4, 0xa4, 0xf7, 0xf6, 0xff,
+ 0xff, 0xff, 0x07, 0xa4, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+ 0x5b, 0xf7, 0xf6, 0xff, 0xf6, 0xf7, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xf7, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0xa4, 0x9b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0xa4, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa4, 0x9b, 0x5b, 0x5b, 0x5b,
+ 0x5b, 0x5b, 0x5b, 0x5b, 0x9b, 0xf7, 0xf6, 0xff, 0xf6, 0xf7, 0xa4, 0xa4,
+ 0xf7, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf7, 0xa4, 0xa4, 0xa4,
+ 0xff, 0xf6, 0xf7, 0xa4, 0xa4, 0xa4, 0x07, 0xff, 0x07, 0xa4, 0xa4, 0xa4,
+ 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xf7, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf6, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x0f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x0f, 0x0f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x57, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xef, 0x0f, 0x0f, 0x4f, 0x4f, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x49, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x57, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0xa7, 0xf6,
+ 0xff, 0xff, 0xff, 0xf6, 0x57, 0x0f, 0x4f, 0x4f, 0x5f, 0xf6, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf6, 0x9f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0xef,
+ 0xff, 0xff, 0xf6, 0xa7, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x0f, 0xaf, 0xff, 0xff, 0xf6, 0xa7, 0x0f, 0x4f, 0x4f, 0x57,
+ 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x52, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x0f, 0x57, 0xef, 0xef, 0xa7, 0x0f, 0x0f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0xaf, 0xef, 0xa7, 0x0f,
+ 0x0f, 0x4f, 0x4f, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa4, 0x00, 0x00,
+ 0x00, 0x49, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf7, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x4f, 0x57, 0x0f, 0x0f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x0f,
+ 0x4f, 0x57, 0x0f, 0x0f, 0x4f, 0x4f, 0x5f, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xf6, 0xa4, 0x52, 0x5b, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x52, 0x52, 0xa4, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xef, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x0f, 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x0f, 0x0f, 0x4f, 0x4f, 0x4f, 0x57, 0xef, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xef, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x57, 0xf6, 0xff, 0x07, 0xa4, 0xf7, 0xf6, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xa7, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xef, 0xff, 0x07, 0x5b,
+ 0x52, 0x52, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0xef, 0x5f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x9f,
+ 0xf6, 0xff, 0xf7, 0x52, 0x52, 0x52, 0xf7, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xef, 0x5f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x5f, 0xf6, 0xff, 0xff, 0x08, 0x5b, 0x52, 0x5b, 0x07, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0xef, 0xa7, 0x5f, 0x57, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
+ 0x4f, 0x4f, 0x4f, 0x5f, 0xa7, 0xef, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xf6,
+ 0x08, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xef, 0xaf, 0xa7, 0xa7,
+ 0xa7, 0xa7, 0xa7, 0xa7, 0xaf, 0xef, 0xef, 0xf6, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+#endif
diff --git a/lib/bch.c b/lib/bch.c
new file mode 100644
index 00000000..c4fac77d
--- /dev/null
+++ b/lib/bch.c
@@ -0,0 +1,1407 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic binary BCH encoding/decoding library
+ *
+ * Copyright © 2011 Parrot S.A.
+ *
+ * Author: Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * Description:
+ *
+ * This library provides runtime configurable encoding/decoding of binary
+ * Bose-Chaudhuri-Hocquenghem (BCH) codes.
+ *
+ * Call init_bch to get a pointer to a newly allocated bch_control structure for
+ * the given m (Galois field order), t (error correction capability) and
+ * (optional) primitive polynomial parameters.
+ *
+ * Call encode_bch to compute and store ecc parity bytes to a given buffer.
+ * Call decode_bch to detect and locate errors in received data.
+ *
+ * On systems supporting hw BCH features, intermediate results may be provided
+ * to decode_bch in order to skip certain steps. See decode_bch() documentation
+ * for details.
+ *
+ * Option CONFIG_BCH_CONST_PARAMS can be used to force fixed values of
+ * parameters m and t; thus allowing extra compiler optimizations and providing
+ * better (up to 2x) encoding performance. Using this option makes sense when
+ * (m,t) are fixed and known in advance, e.g. when using BCH error correction
+ * on a particular NAND flash device.
+ *
+ * Algorithmic details:
+ *
+ * Encoding is performed by processing 32 input bits in parallel, using 4
+ * remainder lookup tables.
+ *
+ * The final stage of decoding involves the following internal steps:
+ * a. Syndrome computation
+ * b. Error locator polynomial computation using Berlekamp-Massey algorithm
+ * c. Error locator root finding (by far the most expensive step)
+ *
+ * In this implementation, step c is not performed using the usual Chien search.
+ * Instead, an alternative approach described in [1] is used. It consists in
+ * factoring the error locator polynomial using the Berlekamp Trace algorithm
+ * (BTA) down to a certain degree (4), after which ad hoc low-degree polynomial
+ * solving techniques [2] are used. The resulting algorithm, called BTZ, yields
+ * much better performance than Chien search for usual (m,t) values (typically
+ * m >= 13, t < 32, see [1]).
+ *
+ * [1] B. Biswas, V. Herbert. Efficient root finding of polynomials over fields
+ * of characteristic 2, in: Western European Workshop on Research in Cryptology
+ * - WEWoRC 2009, Graz, Austria, LNCS, Springer, July 2009, to appear.
+ * [2] [Zin96] V.A. Zinoviev. On the solution of equations of degree 10 over
+ * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <ubi_uboot.h>
+
+#include <linux/bitops.h>
+#else
+#include <errno.h>
+#if defined(__FreeBSD__)
+#include <sys/endian.h>
+#elif defined(__APPLE__)
+#include <machine/endian.h>
+#include <libkern/OSByteOrder.h>
+#else
+#include <endian.h>
+#endif
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef cpu_to_be32
+#if defined(__APPLE__)
+#define cpu_to_be32 OSSwapHostToBigInt32
+#else
+#define cpu_to_be32 htobe32
+#endif
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define kmalloc(size, flags) malloc(size)
+#define kzalloc(size, flags) calloc(1, size)
+#define kfree free
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#include <asm/byteorder.h>
+#include <linux/bch.h>
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+#define GF_M(_p) (CONFIG_BCH_CONST_M)
+#define GF_T(_p) (CONFIG_BCH_CONST_T)
+#define GF_N(_p) ((1 << (CONFIG_BCH_CONST_M))-1)
+#else
+#define GF_M(_p) ((_p)->m)
+#define GF_T(_p) ((_p)->t)
+#define GF_N(_p) ((_p)->n)
+#endif
+
+#define BCH_ECC_WORDS(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
+#define BCH_ECC_BYTES(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
+
+#ifndef dbg
+#define dbg(_fmt, args...) do {} while (0)
+#endif
+
+/*
+ * represent a polynomial over GF(2^m)
+ */
+struct gf_poly {
+ unsigned int deg; /* polynomial degree */
+ unsigned int c[0]; /* polynomial terms */
+};
+
+/* given its degree, compute a polynomial size in bytes */
+#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
+
+/* polynomial of degree 1 */
+struct gf_poly_deg1 {
+ struct gf_poly poly;
+ unsigned int c[2];
+};
+
+#ifdef USE_HOSTCC
+#if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__APPLE__)
+static int fls(int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+#endif
+#endif
+
+/*
+ * same as encode_bch(), but process input data one byte at a time
+ */
+static void encode_bch_unaligned(struct bch_control *bch,
+ const unsigned char *data, unsigned int len,
+ uint32_t *ecc)
+{
+ int i;
+ const uint32_t *p;
+ const int l = BCH_ECC_WORDS(bch)-1;
+
+ while (len--) {
+ p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
+
+ for (i = 0; i < l; i++)
+ ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
+
+ ecc[l] = (ecc[l] << 8)^(*p);
+ }
+}
+
+/*
+ * convert ecc bytes to aligned, zero-padded 32-bit ecc words
+ */
+static void load_ecc8(struct bch_control *bch, uint32_t *dst,
+ const uint8_t *src)
+{
+ uint8_t pad[4] = {0, 0, 0, 0};
+ unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+ for (i = 0; i < nwords; i++, src += 4)
+ dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
+
+ memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
+ dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
+}
+
+/*
+ * convert 32-bit ecc words to ecc bytes
+ */
+static void store_ecc8(struct bch_control *bch, uint8_t *dst,
+ const uint32_t *src)
+{
+ uint8_t pad[4];
+ unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+ for (i = 0; i < nwords; i++) {
+ *dst++ = (src[i] >> 24);
+ *dst++ = (src[i] >> 16) & 0xff;
+ *dst++ = (src[i] >> 8) & 0xff;
+ *dst++ = (src[i] >> 0) & 0xff;
+ }
+ pad[0] = (src[nwords] >> 24);
+ pad[1] = (src[nwords] >> 16) & 0xff;
+ pad[2] = (src[nwords] >> 8) & 0xff;
+ pad[3] = (src[nwords] >> 0) & 0xff;
+ memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
+}
+
+/**
+ * encode_bch - calculate BCH ecc parity of data
+ * @bch: BCH control structure
+ * @data: data to encode
+ * @len: data length in bytes
+ * @ecc: ecc parity data, must be initialized by caller
+ *
+ * The @ecc parity array is used both as input and output parameter, in order to
+ * allow incremental computations. It should be of the size indicated by member
+ * @ecc_bytes of @bch, and should be initialized to 0 before the first call.
+ *
+ * The exact number of computed ecc parity bits is given by member @ecc_bits of
+ * @bch; it may be less than m*t for large values of t.
+ */
+void encode_bch(struct bch_control *bch, const uint8_t *data,
+ unsigned int len, uint8_t *ecc)
+{
+ const unsigned int l = BCH_ECC_WORDS(bch)-1;
+ unsigned int i, mlen;
+ unsigned long m;
+ uint32_t w, r[l+1];
+ const uint32_t * const tab0 = bch->mod8_tab;
+ const uint32_t * const tab1 = tab0 + 256*(l+1);
+ const uint32_t * const tab2 = tab1 + 256*(l+1);
+ const uint32_t * const tab3 = tab2 + 256*(l+1);
+ const uint32_t *pdata, *p0, *p1, *p2, *p3;
+
+ if (ecc) {
+ /* load ecc parity bytes into internal 32-bit buffer */
+ load_ecc8(bch, bch->ecc_buf, ecc);
+ } else {
+ memset(bch->ecc_buf, 0, sizeof(r));
+ }
+
+ /* process first unaligned data bytes */
+ m = ((unsigned long)data) & 3;
+ if (m) {
+ mlen = (len < (4-m)) ? len : 4-m;
+ encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
+ data += mlen;
+ len -= mlen;
+ }
+
+ /* process 32-bit aligned data words */
+ pdata = (uint32_t *)data;
+ mlen = len/4;
+ data += 4*mlen;
+ len -= 4*mlen;
+ memcpy(r, bch->ecc_buf, sizeof(r));
+
+ /*
+ * split each 32-bit word into 4 polynomials of weight 8 as follows:
+ *
+ * 31 ...24 23 ...16 15 ... 8 7 ... 0
+ * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt
+ * tttttttt mod g = r0 (precomputed)
+ * zzzzzzzz 00000000 mod g = r1 (precomputed)
+ * yyyyyyyy 00000000 00000000 mod g = r2 (precomputed)
+ * xxxxxxxx 00000000 00000000 00000000 mod g = r3 (precomputed)
+ * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt mod g = r0^r1^r2^r3
+ */
+ while (mlen--) {
+ /* input data is read in big-endian format */
+ w = r[0]^cpu_to_be32(*pdata++);
+ p0 = tab0 + (l+1)*((w >> 0) & 0xff);
+ p1 = tab1 + (l+1)*((w >> 8) & 0xff);
+ p2 = tab2 + (l+1)*((w >> 16) & 0xff);
+ p3 = tab3 + (l+1)*((w >> 24) & 0xff);
+
+ for (i = 0; i < l; i++)
+ r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
+
+ r[l] = p0[l]^p1[l]^p2[l]^p3[l];
+ }
+ memcpy(bch->ecc_buf, r, sizeof(r));
+
+ /* process last unaligned bytes */
+ if (len)
+ encode_bch_unaligned(bch, data, len, bch->ecc_buf);
+
+ /* store ecc parity bytes into original parity buffer */
+ if (ecc)
+ store_ecc8(bch, ecc, bch->ecc_buf);
+}
+
+static inline int modulo(struct bch_control *bch, unsigned int v)
+{
+ const unsigned int n = GF_N(bch);
+ while (v >= n) {
+ v -= n;
+ v = (v & n) + (v >> GF_M(bch));
+ }
+ return v;
+}
+
+/*
+ * shorter and faster modulo function, only works when v < 2N.
+ */
+static inline int mod_s(struct bch_control *bch, unsigned int v)
+{
+ const unsigned int n = GF_N(bch);
+ return (v < n) ? v : v-n;
+}
+
+static inline int deg(unsigned int poly)
+{
+ /* polynomial degree is the most-significant bit index */
+ return fls(poly)-1;
+}
+
+static inline int parity(unsigned int x)
+{
+ /*
+ * public domain code snippet, lifted from
+ * http://www-graphics.stanford.edu/~seander/bithacks.html
+ */
+ x ^= x >> 1;
+ x ^= x >> 2;
+ x = (x & 0x11111111U) * 0x11111111U;
+ return (x >> 28) & 1;
+}
+
+/* Galois field basic operations: multiply, divide, inverse, etc. */
+
+static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
+ unsigned int b)
+{
+ return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+ bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
+{
+ return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
+}
+
+static inline unsigned int gf_div(struct bch_control *bch, unsigned int a,
+ unsigned int b)
+{
+ return a ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+ GF_N(bch)-bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_inv(struct bch_control *bch, unsigned int a)
+{
+ return bch->a_pow_tab[GF_N(bch)-bch->a_log_tab[a]];
+}
+
+static inline unsigned int a_pow(struct bch_control *bch, int i)
+{
+ return bch->a_pow_tab[modulo(bch, i)];
+}
+
+static inline int a_log(struct bch_control *bch, unsigned int x)
+{
+ return bch->a_log_tab[x];
+}
+
+static inline int a_ilog(struct bch_control *bch, unsigned int x)
+{
+ return mod_s(bch, GF_N(bch)-bch->a_log_tab[x]);
+}
+
+/*
+ * compute 2t syndromes of ecc polynomial, i.e. ecc(a^j) for j=1..2t
+ */
+static void compute_syndromes(struct bch_control *bch, uint32_t *ecc,
+ unsigned int *syn)
+{
+ int i, j, s;
+ unsigned int m;
+ uint32_t poly;
+ const int t = GF_T(bch);
+
+ s = bch->ecc_bits;
+
+ /* make sure extra bits in last ecc word are cleared */
+ m = ((unsigned int)s) & 31;
+ if (m)
+ ecc[s/32] &= ~((1u << (32-m))-1);
+ memset(syn, 0, 2*t*sizeof(*syn));
+
+ /* compute v(a^j) for j=1 .. 2t-1 */
+ do {
+ poly = *ecc++;
+ s -= 32;
+ while (poly) {
+ i = deg(poly);
+ for (j = 0; j < 2*t; j += 2)
+ syn[j] ^= a_pow(bch, (j+1)*(i+s));
+
+ poly ^= (1 << i);
+ }
+ } while (s > 0);
+
+ /* v(a^(2j)) = v(a^j)^2 */
+ for (j = 0; j < t; j++)
+ syn[2*j+1] = gf_sqr(bch, syn[j]);
+}
+
+static void gf_poly_copy(struct gf_poly *dst, struct gf_poly *src)
+{
+ memcpy(dst, src, GF_POLY_SZ(src->deg));
+}
+
+static int compute_error_locator_polynomial(struct bch_control *bch,
+ const unsigned int *syn)
+{
+ const unsigned int t = GF_T(bch);
+ const unsigned int n = GF_N(bch);
+ unsigned int i, j, tmp, l, pd = 1, d = syn[0];
+ struct gf_poly *elp = bch->elp;
+ struct gf_poly *pelp = bch->poly_2t[0];
+ struct gf_poly *elp_copy = bch->poly_2t[1];
+ int k, pp = -1;
+
+ memset(pelp, 0, GF_POLY_SZ(2*t));
+ memset(elp, 0, GF_POLY_SZ(2*t));
+
+ pelp->deg = 0;
+ pelp->c[0] = 1;
+ elp->deg = 0;
+ elp->c[0] = 1;
+
+ /* use simplified binary Berlekamp-Massey algorithm */
+ for (i = 0; (i < t) && (elp->deg <= t); i++) {
+ if (d) {
+ k = 2*i-pp;
+ gf_poly_copy(elp_copy, elp);
+ /* e[i+1](X) = e[i](X)+di*dp^-1*X^2(i-p)*e[p](X) */
+ tmp = a_log(bch, d)+n-a_log(bch, pd);
+ for (j = 0; j <= pelp->deg; j++) {
+ if (pelp->c[j]) {
+ l = a_log(bch, pelp->c[j]);
+ elp->c[j+k] ^= a_pow(bch, tmp+l);
+ }
+ }
+ /* compute l[i+1] = max(l[i]->c[l[p]+2*(i-p]) */
+ tmp = pelp->deg+k;
+ if (tmp > elp->deg) {
+ elp->deg = tmp;
+ gf_poly_copy(pelp, elp_copy);
+ pd = d;
+ pp = 2*i;
+ }
+ }
+ /* di+1 = S(2i+3)+elp[i+1].1*S(2i+2)+...+elp[i+1].lS(2i+3-l) */
+ if (i < t-1) {
+ d = syn[2*i+2];
+ for (j = 1; j <= elp->deg; j++)
+ d ^= gf_mul(bch, elp->c[j], syn[2*i+2-j]);
+ }
+ }
+ dbg("elp=%s\n", gf_poly_str(elp));
+ return (elp->deg > t) ? -1 : (int)elp->deg;
+}
+
+/*
+ * solve a m x m linear system in GF(2) with an expected number of solutions,
+ * and return the number of found solutions
+ */
+static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
+ unsigned int *sol, int nsol)
+{
+ const int m = GF_M(bch);
+ unsigned int tmp, mask;
+ int rem, c, r, p, k, param[m];
+
+ k = 0;
+ mask = 1 << m;
+
+ /* Gaussian elimination */
+ for (c = 0; c < m; c++) {
+ rem = 0;
+ p = c-k;
+ /* find suitable row for elimination */
+ for (r = p; r < m; r++) {
+ if (rows[r] & mask) {
+ if (r != p) {
+ tmp = rows[r];
+ rows[r] = rows[p];
+ rows[p] = tmp;
+ }
+ rem = r+1;
+ break;
+ }
+ }
+ if (rem) {
+ /* perform elimination on remaining rows */
+ tmp = rows[p];
+ for (r = rem; r < m; r++) {
+ if (rows[r] & mask)
+ rows[r] ^= tmp;
+ }
+ } else {
+ /* elimination not needed, store defective row index */
+ param[k++] = c;
+ }
+ mask >>= 1;
+ }
+ /* rewrite system, inserting fake parameter rows */
+ if (k > 0) {
+ p = k;
+ for (r = m-1; r >= 0; r--) {
+ if ((r > m-1-k) && rows[r])
+ /* system has no solution */
+ return 0;
+
+ rows[r] = (p && (r == param[p-1])) ?
+ p--, 1u << (m-r) : rows[r-p];
+ }
+ }
+
+ if (nsol != (1 << k))
+ /* unexpected number of solutions */
+ return 0;
+
+ for (p = 0; p < nsol; p++) {
+ /* set parameters for p-th solution */
+ for (c = 0; c < k; c++)
+ rows[param[c]] = (rows[param[c]] & ~1)|((p >> c) & 1);
+
+ /* compute unique solution */
+ tmp = 0;
+ for (r = m-1; r >= 0; r--) {
+ mask = rows[r] & (tmp|1);
+ tmp |= parity(mask) << (m-r);
+ }
+ sol[p] = tmp >> 1;
+ }
+ return nsol;
+}
+
+/*
+ * this function builds and solves a linear system for finding roots of a degree
+ * 4 affine monic polynomial X^4+aX^2+bX+c over GF(2^m).
+ */
+static int find_affine4_roots(struct bch_control *bch, unsigned int a,
+ unsigned int b, unsigned int c,
+ unsigned int *roots)
+{
+ int i, j, k;
+ const int m = GF_M(bch);
+ unsigned int mask = 0xff, t, rows[16] = {0,};
+
+ j = a_log(bch, b);
+ k = a_log(bch, a);
+ rows[0] = c;
+
+ /* buid linear system to solve X^4+aX^2+bX+c = 0 */
+ for (i = 0; i < m; i++) {
+ rows[i+1] = bch->a_pow_tab[4*i]^
+ (a ? bch->a_pow_tab[mod_s(bch, k)] : 0)^
+ (b ? bch->a_pow_tab[mod_s(bch, j)] : 0);
+ j++;
+ k += 2;
+ }
+ /*
+ * transpose 16x16 matrix before passing it to linear solver
+ * warning: this code assumes m < 16
+ */
+ for (j = 8; j != 0; j >>= 1, mask ^= (mask << j)) {
+ for (k = 0; k < 16; k = (k+j+1) & ~j) {
+ t = ((rows[k] >> j)^rows[k+j]) & mask;
+ rows[k] ^= (t << j);
+ rows[k+j] ^= t;
+ }
+ }
+ return solve_linear_system(bch, rows, roots, 4);
+}
+
+/*
+ * compute root r of a degree 1 polynomial over GF(2^m) (returned as log(1/r))
+ */
+static int find_poly_deg1_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int n = 0;
+
+ if (poly->c[0])
+ /* poly[X] = bX+c with c!=0, root=c/b */
+ roots[n++] = mod_s(bch, GF_N(bch)-bch->a_log_tab[poly->c[0]]+
+ bch->a_log_tab[poly->c[1]]);
+ return n;
+}
+
+/*
+ * compute roots of a degree 2 polynomial over GF(2^m)
+ */
+static int find_poly_deg2_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int n = 0, i, l0, l1, l2;
+ unsigned int u, v, r;
+
+ if (poly->c[0] && poly->c[1]) {
+
+ l0 = bch->a_log_tab[poly->c[0]];
+ l1 = bch->a_log_tab[poly->c[1]];
+ l2 = bch->a_log_tab[poly->c[2]];
+
+ /* using z=a/bX, transform aX^2+bX+c into z^2+z+u (u=ac/b^2) */
+ u = a_pow(bch, l0+l2+2*(GF_N(bch)-l1));
+ /*
+ * let u = sum(li.a^i) i=0..m-1; then compute r = sum(li.xi):
+ * r^2+r = sum(li.(xi^2+xi)) = sum(li.(a^i+Tr(a^i).a^k)) =
+ * u + sum(li.Tr(a^i).a^k) = u+a^k.Tr(sum(li.a^i)) = u+a^k.Tr(u)
+ * i.e. r and r+1 are roots iff Tr(u)=0
+ */
+ r = 0;
+ v = u;
+ while (v) {
+ i = deg(v);
+ r ^= bch->xi_tab[i];
+ v ^= (1 << i);
+ }
+ /* verify root */
+ if ((gf_sqr(bch, r)^r) == u) {
+ /* reverse z=a/bX transformation and compute log(1/r) */
+ roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+ bch->a_log_tab[r]+l2);
+ roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+ bch->a_log_tab[r^1]+l2);
+ }
+ }
+ return n;
+}
+
+/*
+ * compute roots of a degree 3 polynomial over GF(2^m)
+ */
+static int find_poly_deg3_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int i, n = 0;
+ unsigned int a, b, c, a2, b2, c2, e3, tmp[4];
+
+ if (poly->c[0]) {
+ /* transform polynomial into monic X^3 + a2X^2 + b2X + c2 */
+ e3 = poly->c[3];
+ c2 = gf_div(bch, poly->c[0], e3);
+ b2 = gf_div(bch, poly->c[1], e3);
+ a2 = gf_div(bch, poly->c[2], e3);
+
+ /* (X+a2)(X^3+a2X^2+b2X+c2) = X^4+aX^2+bX+c (affine) */
+ c = gf_mul(bch, a2, c2); /* c = a2c2 */
+ b = gf_mul(bch, a2, b2)^c2; /* b = a2b2 + c2 */
+ a = gf_sqr(bch, a2)^b2; /* a = a2^2 + b2 */
+
+ /* find the 4 roots of this affine polynomial */
+ if (find_affine4_roots(bch, a, b, c, tmp) == 4) {
+ /* remove a2 from final list of roots */
+ for (i = 0; i < 4; i++) {
+ if (tmp[i] != a2)
+ roots[n++] = a_ilog(bch, tmp[i]);
+ }
+ }
+ }
+ return n;
+}
+
+/*
+ * compute roots of a degree 4 polynomial over GF(2^m)
+ */
+static int find_poly_deg4_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int i, l, n = 0;
+ unsigned int a, b, c, d, e = 0, f, a2, b2, c2, e4;
+
+ if (poly->c[0] == 0)
+ return 0;
+
+ /* transform polynomial into monic X^4 + aX^3 + bX^2 + cX + d */
+ e4 = poly->c[4];
+ d = gf_div(bch, poly->c[0], e4);
+ c = gf_div(bch, poly->c[1], e4);
+ b = gf_div(bch, poly->c[2], e4);
+ a = gf_div(bch, poly->c[3], e4);
+
+ /* use Y=1/X transformation to get an affine polynomial */
+ if (a) {
+ /* first, eliminate cX by using z=X+e with ae^2+c=0 */
+ if (c) {
+ /* compute e such that e^2 = c/a */
+ f = gf_div(bch, c, a);
+ l = a_log(bch, f);
+ l += (l & 1) ? GF_N(bch) : 0;
+ e = a_pow(bch, l/2);
+ /*
+ * use transformation z=X+e:
+ * z^4+e^4 + a(z^3+ez^2+e^2z+e^3) + b(z^2+e^2) +cz+ce+d
+ * z^4 + az^3 + (ae+b)z^2 + (ae^2+c)z+e^4+be^2+ae^3+ce+d
+ * z^4 + az^3 + (ae+b)z^2 + e^4+be^2+d
+ * z^4 + az^3 + b'z^2 + d'
+ */
+ d = a_pow(bch, 2*l)^gf_mul(bch, b, f)^d;
+ b = gf_mul(bch, a, e)^b;
+ }
+ /* now, use Y=1/X to get Y^4 + b/dY^2 + a/dY + 1/d */
+ if (d == 0)
+ /* assume all roots have multiplicity 1 */
+ return 0;
+
+ c2 = gf_inv(bch, d);
+ b2 = gf_div(bch, a, d);
+ a2 = gf_div(bch, b, d);
+ } else {
+ /* polynomial is already affine */
+ c2 = d;
+ b2 = c;
+ a2 = b;
+ }
+ /* find the 4 roots of this affine polynomial */
+ if (find_affine4_roots(bch, a2, b2, c2, roots) == 4) {
+ for (i = 0; i < 4; i++) {
+ /* post-process roots (reverse transformations) */
+ f = a ? gf_inv(bch, roots[i]) : roots[i];
+ roots[i] = a_ilog(bch, f^e);
+ }
+ n = 4;
+ }
+ return n;
+}
+
+/*
+ * build monic, log-based representation of a polynomial
+ */
+static void gf_poly_logrep(struct bch_control *bch,
+ const struct gf_poly *a, int *rep)
+{
+ int i, d = a->deg, l = GF_N(bch)-a_log(bch, a->c[a->deg]);
+
+ /* represent 0 values with -1; warning, rep[d] is not set to 1 */
+ for (i = 0; i < d; i++)
+ rep[i] = a->c[i] ? mod_s(bch, a_log(bch, a->c[i])+l) : -1;
+}
+
+/*
+ * compute polynomial Euclidean division remainder in GF(2^m)[X]
+ */
+static void gf_poly_mod(struct bch_control *bch, struct gf_poly *a,
+ const struct gf_poly *b, int *rep)
+{
+ int la, p, m;
+ unsigned int i, j, *c = a->c;
+ const unsigned int d = b->deg;
+
+ if (a->deg < d)
+ return;
+
+ /* reuse or compute log representation of denominator */
+ if (!rep) {
+ rep = bch->cache;
+ gf_poly_logrep(bch, b, rep);
+ }
+
+ for (j = a->deg; j >= d; j--) {
+ if (c[j]) {
+ la = a_log(bch, c[j]);
+ p = j-d;
+ for (i = 0; i < d; i++, p++) {
+ m = rep[i];
+ if (m >= 0)
+ c[p] ^= bch->a_pow_tab[mod_s(bch,
+ m+la)];
+ }
+ }
+ }
+ a->deg = d-1;
+ while (!c[a->deg] && a->deg)
+ a->deg--;
+}
+
+/*
+ * compute polynomial Euclidean division quotient in GF(2^m)[X]
+ */
+static void gf_poly_div(struct bch_control *bch, struct gf_poly *a,
+ const struct gf_poly *b, struct gf_poly *q)
+{
+ if (a->deg >= b->deg) {
+ q->deg = a->deg-b->deg;
+ /* compute a mod b (modifies a) */
+ gf_poly_mod(bch, a, b, NULL);
+ /* quotient is stored in upper part of polynomial a */
+ memcpy(q->c, &a->c[b->deg], (1+q->deg)*sizeof(unsigned int));
+ } else {
+ q->deg = 0;
+ q->c[0] = 0;
+ }
+}
+
+/*
+ * compute polynomial GCD (Greatest Common Divisor) in GF(2^m)[X]
+ */
+static struct gf_poly *gf_poly_gcd(struct bch_control *bch, struct gf_poly *a,
+ struct gf_poly *b)
+{
+ struct gf_poly *tmp;
+
+ dbg("gcd(%s,%s)=", gf_poly_str(a), gf_poly_str(b));
+
+ if (a->deg < b->deg) {
+ tmp = b;
+ b = a;
+ a = tmp;
+ }
+
+ while (b->deg > 0) {
+ gf_poly_mod(bch, a, b, NULL);
+ tmp = b;
+ b = a;
+ a = tmp;
+ }
+
+ dbg("%s\n", gf_poly_str(a));
+
+ return a;
+}
+
+/*
+ * Given a polynomial f and an integer k, compute Tr(a^kX) mod f
+ * This is used in Berlekamp Trace algorithm for splitting polynomials
+ */
+static void compute_trace_bk_mod(struct bch_control *bch, int k,
+ const struct gf_poly *f, struct gf_poly *z,
+ struct gf_poly *out)
+{
+ const int m = GF_M(bch);
+ int i, j;
+
+ /* z contains z^2j mod f */
+ z->deg = 1;
+ z->c[0] = 0;
+ z->c[1] = bch->a_pow_tab[k];
+
+ out->deg = 0;
+ memset(out, 0, GF_POLY_SZ(f->deg));
+
+ /* compute f log representation only once */
+ gf_poly_logrep(bch, f, bch->cache);
+
+ for (i = 0; i < m; i++) {
+ /* add a^(k*2^i)(z^(2^i) mod f) and compute (z^(2^i) mod f)^2 */
+ for (j = z->deg; j >= 0; j--) {
+ out->c[j] ^= z->c[j];
+ z->c[2*j] = gf_sqr(bch, z->c[j]);
+ z->c[2*j+1] = 0;
+ }
+ if (z->deg > out->deg)
+ out->deg = z->deg;
+
+ if (i < m-1) {
+ z->deg *= 2;
+ /* z^(2(i+1)) mod f = (z^(2^i) mod f)^2 mod f */
+ gf_poly_mod(bch, z, f, bch->cache);
+ }
+ }
+ while (!out->c[out->deg] && out->deg)
+ out->deg--;
+
+ dbg("Tr(a^%d.X) mod f = %s\n", k, gf_poly_str(out));
+}
+
+/*
+ * factor a polynomial using Berlekamp Trace algorithm (BTA)
+ */
+static void factor_polynomial(struct bch_control *bch, int k, struct gf_poly *f,
+ struct gf_poly **g, struct gf_poly **h)
+{
+ struct gf_poly *f2 = bch->poly_2t[0];
+ struct gf_poly *q = bch->poly_2t[1];
+ struct gf_poly *tk = bch->poly_2t[2];
+ struct gf_poly *z = bch->poly_2t[3];
+ struct gf_poly *gcd;
+
+ dbg("factoring %s...\n", gf_poly_str(f));
+
+ *g = f;
+ *h = NULL;
+
+ /* tk = Tr(a^k.X) mod f */
+ compute_trace_bk_mod(bch, k, f, z, tk);
+
+ if (tk->deg > 0) {
+ /* compute g = gcd(f, tk) (destructive operation) */
+ gf_poly_copy(f2, f);
+ gcd = gf_poly_gcd(bch, f2, tk);
+ if (gcd->deg < f->deg) {
+ /* compute h=f/gcd(f,tk); this will modify f and q */
+ gf_poly_div(bch, f, gcd, q);
+ /* store g and h in-place (clobbering f) */
+ *h = &((struct gf_poly_deg1 *)f)[gcd->deg].poly;
+ gf_poly_copy(*g, gcd);
+ gf_poly_copy(*h, q);
+ }
+ }
+}
+
+/*
+ * find roots of a polynomial, using BTZ algorithm; see the beginning of this
+ * file for details
+ */
+static int find_poly_roots(struct bch_control *bch, unsigned int k,
+ struct gf_poly *poly, unsigned int *roots)
+{
+ int cnt;
+ struct gf_poly *f1, *f2;
+
+ switch (poly->deg) {
+ /* handle low degree polynomials with ad hoc techniques */
+ case 1:
+ cnt = find_poly_deg1_roots(bch, poly, roots);
+ break;
+ case 2:
+ cnt = find_poly_deg2_roots(bch, poly, roots);
+ break;
+ case 3:
+ cnt = find_poly_deg3_roots(bch, poly, roots);
+ break;
+ case 4:
+ cnt = find_poly_deg4_roots(bch, poly, roots);
+ break;
+ default:
+ /* factor polynomial using Berlekamp Trace Algorithm (BTA) */
+ cnt = 0;
+ if (poly->deg && (k <= GF_M(bch))) {
+ factor_polynomial(bch, k, poly, &f1, &f2);
+ if (f1)
+ cnt += find_poly_roots(bch, k+1, f1, roots);
+ if (f2)
+ cnt += find_poly_roots(bch, k+1, f2, roots+cnt);
+ }
+ break;
+ }
+ return cnt;
+}
+
+#if defined(USE_CHIEN_SEARCH)
+/*
+ * exhaustive root search (Chien) implementation - not used, included only for
+ * reference/comparison tests
+ */
+static int chien_search(struct bch_control *bch, unsigned int len,
+ struct gf_poly *p, unsigned int *roots)
+{
+ int m;
+ unsigned int i, j, syn, syn0, count = 0;
+ const unsigned int k = 8*len+bch->ecc_bits;
+
+ /* use a log-based representation of polynomial */
+ gf_poly_logrep(bch, p, bch->cache);
+ bch->cache[p->deg] = 0;
+ syn0 = gf_div(bch, p->c[0], p->c[p->deg]);
+
+ for (i = GF_N(bch)-k+1; i <= GF_N(bch); i++) {
+ /* compute elp(a^i) */
+ for (j = 1, syn = syn0; j <= p->deg; j++) {
+ m = bch->cache[j];
+ if (m >= 0)
+ syn ^= a_pow(bch, m+j*i);
+ }
+ if (syn == 0) {
+ roots[count++] = GF_N(bch)-i;
+ if (count == p->deg)
+ break;
+ }
+ }
+ return (count == p->deg) ? count : 0;
+}
+#define find_poly_roots(_p, _k, _elp, _loc) chien_search(_p, len, _elp, _loc)
+#endif /* USE_CHIEN_SEARCH */
+
+/**
+ * decode_bch - decode received codeword and find bit error locations
+ * @bch: BCH control structure
+ * @data: received data, ignored if @calc_ecc is provided
+ * @len: data length in bytes, must always be provided
+ * @recv_ecc: received ecc, if NULL then assume it was XORed in @calc_ecc
+ * @calc_ecc: calculated ecc, if NULL then calc_ecc is computed from @data
+ * @syn: hw computed syndrome data (if NULL, syndrome is calculated)
+ * @errloc: output array of error locations
+ *
+ * Returns:
+ * The number of errors found, or -EBADMSG if decoding failed, or -EINVAL if
+ * invalid parameters were provided
+ *
+ * Depending on the available hw BCH support and the need to compute @calc_ecc
+ * separately (using encode_bch()), this function should be called with one of
+ * the following parameter configurations -
+ *
+ * by providing @data and @recv_ecc only:
+ * decode_bch(@bch, @data, @len, @recv_ecc, NULL, NULL, @errloc)
+ *
+ * by providing @recv_ecc and @calc_ecc:
+ * decode_bch(@bch, NULL, @len, @recv_ecc, @calc_ecc, NULL, @errloc)
+ *
+ * by providing ecc = recv_ecc XOR calc_ecc:
+ * decode_bch(@bch, NULL, @len, NULL, ecc, NULL, @errloc)
+ *
+ * by providing syndrome results @syn:
+ * decode_bch(@bch, NULL, @len, NULL, NULL, @syn, @errloc)
+ *
+ * Once decode_bch() has successfully returned with a positive value, error
+ * locations returned in array @errloc should be interpreted as follows -
+ *
+ * if (errloc[n] >= 8*len), then n-th error is located in ecc (no need for
+ * data correction)
+ *
+ * if (errloc[n] < 8*len), then n-th error is located in data and can be
+ * corrected with statement data[errloc[n]/8] ^= 1 << (errloc[n] % 8);
+ *
+ * Note that this function does not perform any data correction by itself, it
+ * merely indicates error locations.
+ */
+int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
+ const uint8_t *recv_ecc, const uint8_t *calc_ecc,
+ const unsigned int *syn, unsigned int *errloc)
+{
+ const unsigned int ecc_words = BCH_ECC_WORDS(bch);
+ unsigned int nbits;
+ int i, err, nroots;
+ uint32_t sum;
+
+ /* sanity check: make sure data length can be handled */
+ if (8*len > (bch->n-bch->ecc_bits))
+ return -EINVAL;
+
+ /* if caller does not provide syndromes, compute them */
+ if (!syn) {
+ if (!calc_ecc) {
+ /* compute received data ecc into an internal buffer */
+ if (!data || !recv_ecc)
+ return -EINVAL;
+ encode_bch(bch, data, len, NULL);
+ } else {
+ /* load provided calculated ecc */
+ load_ecc8(bch, bch->ecc_buf, calc_ecc);
+ }
+ /* load received ecc or assume it was XORed in calc_ecc */
+ if (recv_ecc) {
+ load_ecc8(bch, bch->ecc_buf2, recv_ecc);
+ /* XOR received and calculated ecc */
+ for (i = 0, sum = 0; i < (int)ecc_words; i++) {
+ bch->ecc_buf[i] ^= bch->ecc_buf2[i];
+ sum |= bch->ecc_buf[i];
+ }
+ if (!sum)
+ /* no error found */
+ return 0;
+ }
+ compute_syndromes(bch, bch->ecc_buf, bch->syn);
+ syn = bch->syn;
+ }
+
+ err = compute_error_locator_polynomial(bch, syn);
+ if (err > 0) {
+ nroots = find_poly_roots(bch, 1, bch->elp, errloc);
+ if (err != nroots)
+ err = -1;
+ }
+ if (err > 0) {
+ /* post-process raw error locations for easier correction */
+ nbits = (len*8)+bch->ecc_bits;
+ for (i = 0; i < err; i++) {
+ if (errloc[i] >= nbits) {
+ err = -1;
+ break;
+ }
+ errloc[i] = nbits-1-errloc[i];
+ errloc[i] = (errloc[i] & ~7)|(7-(errloc[i] & 7));
+ }
+ }
+ return (err >= 0) ? err : -EBADMSG;
+}
+
+/*
+ * generate Galois field lookup tables
+ */
+static int build_gf_tables(struct bch_control *bch, unsigned int poly)
+{
+ unsigned int i, x = 1;
+ const unsigned int k = 1 << deg(poly);
+
+ /* primitive polynomial must be of degree m */
+ if (k != (1u << GF_M(bch)))
+ return -1;
+
+ for (i = 0; i < GF_N(bch); i++) {
+ bch->a_pow_tab[i] = x;
+ bch->a_log_tab[x] = i;
+ if (i && (x == 1))
+ /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+ return -1;
+ x <<= 1;
+ if (x & k)
+ x ^= poly;
+ }
+ bch->a_pow_tab[GF_N(bch)] = 1;
+ bch->a_log_tab[0] = 0;
+
+ return 0;
+}
+
+/*
+ * compute generator polynomial remainder tables for fast encoding
+ */
+static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
+{
+ int i, j, b, d;
+ uint32_t data, hi, lo, *tab;
+ const int l = BCH_ECC_WORDS(bch);
+ const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
+ const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
+
+ memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
+
+ for (i = 0; i < 256; i++) {
+ /* p(X)=i is a small polynomial of weight <= 8 */
+ for (b = 0; b < 4; b++) {
+ /* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */
+ tab = bch->mod8_tab + (b*256+i)*l;
+ data = i << (8*b);
+ while (data) {
+ d = deg(data);
+ /* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */
+ data ^= g[0] >> (31-d);
+ for (j = 0; j < ecclen; j++) {
+ hi = (d < 31) ? g[j] << (d+1) : 0;
+ lo = (j+1 < plen) ?
+ g[j+1] >> (31-d) : 0;
+ tab[j] ^= hi|lo;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * build a base for factoring degree 2 polynomials
+ */
+static int build_deg2_base(struct bch_control *bch)
+{
+ const int m = GF_M(bch);
+ int i, j, r;
+ unsigned int sum, x, y, remaining, ak = 0, xi[m];
+
+ /* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
+ for (i = 0; i < m; i++) {
+ for (j = 0, sum = 0; j < m; j++)
+ sum ^= a_pow(bch, i*(1 << j));
+
+ if (sum) {
+ ak = bch->a_pow_tab[i];
+ break;
+ }
+ }
+ /* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */
+ remaining = m;
+ memset(xi, 0, sizeof(xi));
+
+ for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
+ y = gf_sqr(bch, x)^x;
+ for (i = 0; i < 2; i++) {
+ r = a_log(bch, y);
+ if (y && (r < m) && !xi[r]) {
+ bch->xi_tab[r] = x;
+ xi[r] = 1;
+ remaining--;
+ dbg("x%d = %x\n", r, x);
+ break;
+ }
+ y ^= ak;
+ }
+ }
+ /* should not happen but check anyway */
+ return remaining ? -1 : 0;
+}
+
+static void *bch_alloc(size_t size, int *err)
+{
+ void *ptr;
+
+ ptr = kmalloc(size, GFP_KERNEL);
+ if (ptr == NULL)
+ *err = 1;
+ return ptr;
+}
+
+/*
+ * compute generator polynomial for given (m,t) parameters.
+ */
+static uint32_t *compute_generator_polynomial(struct bch_control *bch)
+{
+ const unsigned int m = GF_M(bch);
+ const unsigned int t = GF_T(bch);
+ int n, err = 0;
+ unsigned int i, j, nbits, r, word, *roots;
+ struct gf_poly *g;
+ uint32_t *genpoly;
+
+ g = bch_alloc(GF_POLY_SZ(m*t), &err);
+ roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
+ genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
+
+ if (err) {
+ kfree(genpoly);
+ genpoly = NULL;
+ goto finish;
+ }
+
+ /* enumerate all roots of g(X) */
+ memset(roots , 0, (bch->n+1)*sizeof(*roots));
+ for (i = 0; i < t; i++) {
+ for (j = 0, r = 2*i+1; j < m; j++) {
+ roots[r] = 1;
+ r = mod_s(bch, 2*r);
+ }
+ }
+ /* build generator polynomial g(X) */
+ g->deg = 0;
+ g->c[0] = 1;
+ for (i = 0; i < GF_N(bch); i++) {
+ if (roots[i]) {
+ /* multiply g(X) by (X+root) */
+ r = bch->a_pow_tab[i];
+ g->c[g->deg+1] = 1;
+ for (j = g->deg; j > 0; j--)
+ g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
+
+ g->c[0] = gf_mul(bch, g->c[0], r);
+ g->deg++;
+ }
+ }
+ /* store left-justified binary representation of g(X) */
+ n = g->deg+1;
+ i = 0;
+
+ while (n > 0) {
+ nbits = (n > 32) ? 32 : n;
+ for (j = 0, word = 0; j < nbits; j++) {
+ if (g->c[n-1-j])
+ word |= 1u << (31-j);
+ }
+ genpoly[i++] = word;
+ n -= nbits;
+ }
+ bch->ecc_bits = g->deg;
+
+finish:
+ kfree(g);
+ kfree(roots);
+
+ return genpoly;
+}
+
+/**
+ * init_bch - initialize a BCH encoder/decoder
+ * @m: Galois field order, should be in the range 5-15
+ * @t: maximum error correction capability, in bits
+ * @prim_poly: user-provided primitive polynomial (or 0 to use default)
+ *
+ * Returns:
+ * a newly allocated BCH control structure if successful, NULL otherwise
+ *
+ * This initialization can take some time, as lookup tables are built for fast
+ * encoding/decoding; make sure not to call this function from a time critical
+ * path. Usually, init_bch() should be called on module/driver init and
+ * free_bch() should be called to release memory on exit.
+ *
+ * You may provide your own primitive polynomial of degree @m in argument
+ * @prim_poly, or let init_bch() use its default polynomial.
+ *
+ * Once init_bch() has successfully returned a pointer to a newly allocated
+ * BCH control structure, ecc length in bytes is given by member @ecc_bytes of
+ * the structure.
+ */
+struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
+{
+ int err = 0;
+ unsigned int i, words;
+ uint32_t *genpoly;
+ struct bch_control *bch = NULL;
+
+ const int min_m = 5;
+ const int max_m = 15;
+
+ /* default primitive polynomials */
+ static const unsigned int prim_poly_tab[] = {
+ 0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
+ 0x402b, 0x8003,
+ };
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+ if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
+ printk(KERN_ERR "bch encoder/decoder was configured to support "
+ "parameters m=%d, t=%d only!\n",
+ CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
+ goto fail;
+ }
+#endif
+ if ((m < min_m) || (m > max_m))
+ /*
+ * values of m greater than 15 are not currently supported;
+ * supporting m > 15 would require changing table base type
+ * (uint16_t) and a small patch in matrix transposition
+ */
+ goto fail;
+
+ /* sanity checks */
+ if ((t < 1) || (m*t >= ((1 << m)-1)))
+ /* invalid t value */
+ goto fail;
+
+ /* select a primitive polynomial for generating GF(2^m) */
+ if (prim_poly == 0)
+ prim_poly = prim_poly_tab[m-min_m];
+
+ bch = kzalloc(sizeof(*bch), GFP_KERNEL);
+ if (bch == NULL)
+ goto fail;
+
+ bch->m = m;
+ bch->t = t;
+ bch->n = (1 << m)-1;
+ words = DIV_ROUND_UP(m*t, 32);
+ bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
+ bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
+ bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
+ bch->mod8_tab = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
+ bch->ecc_buf = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
+ bch->ecc_buf2 = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
+ bch->xi_tab = bch_alloc(m*sizeof(*bch->xi_tab), &err);
+ bch->syn = bch_alloc(2*t*sizeof(*bch->syn), &err);
+ bch->cache = bch_alloc(2*t*sizeof(*bch->cache), &err);
+ bch->elp = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
+
+ for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+ bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
+
+ if (err)
+ goto fail;
+
+ err = build_gf_tables(bch, prim_poly);
+ if (err)
+ goto fail;
+
+ /* use generator polynomial for computing encoding tables */
+ genpoly = compute_generator_polynomial(bch);
+ if (genpoly == NULL)
+ goto fail;
+
+ build_mod8_tables(bch, genpoly);
+ kfree(genpoly);
+
+ err = build_deg2_base(bch);
+ if (err)
+ goto fail;
+
+ return bch;
+
+fail:
+ free_bch(bch);
+ return NULL;
+}
+
+/**
+ * free_bch - free the BCH control structure
+ * @bch: BCH control structure to release
+ */
+void free_bch(struct bch_control *bch)
+{
+ unsigned int i;
+
+ if (bch) {
+ kfree(bch->a_pow_tab);
+ kfree(bch->a_log_tab);
+ kfree(bch->mod8_tab);
+ kfree(bch->ecc_buf);
+ kfree(bch->ecc_buf2);
+ kfree(bch->xi_tab);
+ kfree(bch->syn);
+ kfree(bch->cache);
+ kfree(bch->elp);
+
+ for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+ kfree(bch->poly_2t[i]);
+
+ kfree(bch);
+ }
+}
diff --git a/lib/bitrev.c b/lib/bitrev.c
new file mode 100644
index 00000000..08231c05
--- /dev/null
+++ b/lib/bitrev.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef CONFIG_HAVE_ARCH_BITREVERSE
+#include <linux/types.h>
+#include <linux/compat.h>
+#include <linux/bitrev.h>
+
+MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
+MODULE_DESCRIPTION("Bit ordering reversal functions");
+MODULE_LICENSE("GPL");
+
+const u8 byte_rev_table[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+EXPORT_SYMBOL_GPL(byte_rev_table);
+
+#endif /* CONFIG_HAVE_ARCH_BITREVERSE */
diff --git a/lib/bzip2/Makefile b/lib/bzip2/Makefile
new file mode 100644
index 00000000..ebdd2976
--- /dev/null
+++ b/lib/bzip2/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += bzlib.o bzlib_crctable.o bzlib_decompress.o \
+ bzlib_randtable.o bzlib_huffman.o
+obj-$(CONFIG_SANDBOX) += bzlib_compress.o bzlib_blocksort.o
diff --git a/lib/bzip2/bzlib.c b/lib/bzip2/bzlib.c
new file mode 100644
index 00000000..9262e405
--- /dev/null
+++ b/lib/bzip2/bzlib.c
@@ -0,0 +1,1601 @@
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+
+/*
+ * This file is a modified version of bzlib.c from the bzip2-1.0.2
+ * distribution which can be found at http://sources.redhat.com/bzip2/
+ */
+
+/*-------------------------------------------------------------*/
+/*--- Library top-level functions. ---*/
+/*--- bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+/*--
+ CHANGES
+ ~~~~~~~
+ 0.9.0 -- original version.
+
+ 0.9.0a/b -- no changes in this file.
+
+ 0.9.0c
+ * made zero-length BZ_FLUSH work correctly in bzCompress().
+ * fixed bzWrite/bzRead to ignore zero-length requests.
+ * fixed bzread to correctly handle read requests after EOF.
+ * wrong parameter order in call to bzDecompressInit in
+ bzBuffToBuffDecompress. Fixed.
+--*/
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------------*/
+/*--- Compression stuff ---*/
+/*---------------------------------------------------*/
+
+
+/*---------------------------------------------------*/
+#ifndef BZ_NO_STDIO
+void BZ2_bz__AssertH__fail ( int errcode )
+{
+ fprintf(stderr,
+ "\n\nbzip2/libbzip2: internal error number %d.\n"
+ "This is a bug in bzip2/libbzip2, %s.\n"
+ "Please report it to me at: jseward@acm.org. If this happened\n"
+ "when you were using some program which uses libbzip2 as a\n"
+ "component, you should also report this bug to the author(s)\n"
+ "of that program. Please make an effort to report this bug;\n"
+ "timely and accurate bug reports eventually lead to higher\n"
+ "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
+ errcode,
+ BZ2_bzlibVersion()
+ );
+
+ if (errcode == 1007) {
+ fprintf(stderr,
+ "\n*** A special note about internal error number 1007 ***\n"
+ "\n"
+ "Experience suggests that a common cause of i.e. 1007\n"
+ "is unreliable memory or other hardware. The 1007 assertion\n"
+ "just happens to cross-check the results of huge numbers of\n"
+ "memory reads/writes, and so acts (unintendedly) as a stress\n"
+ "test of your memory system.\n"
+ "\n"
+ "I suggest the following: try compressing the file again,\n"
+ "possibly monitoring progress in detail with the -vv flag.\n"
+ "\n"
+ "* If the error cannot be reproduced, and/or happens at different\n"
+ " points in compression, you may have a flaky memory system.\n"
+ " Try a memory-test program. I have used Memtest86\n"
+ " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
+ " Memtest86 tests memory much more thorougly than your BIOSs\n"
+ " power-on test, and may find failures that the BIOS doesn't.\n"
+ "\n"
+ "* If the error can be repeatably reproduced, this is a bug in\n"
+ " bzip2, and I would very much like to hear about it. Please\n"
+ " let me know, and, ideally, save a copy of the file causing the\n"
+ " problem -- without which I will be unable to investigate it.\n"
+ "\n"
+ );
+ }
+
+ exit(3);
+}
+#endif
+
+
+/*---------------------------------------------------*/
+static
+int bz_config_ok ( void )
+{
+ if (sizeof(int) != 4) return 0;
+ if (sizeof(short) != 2) return 0;
+ if (sizeof(char) != 1) return 0;
+ return 1;
+}
+
+
+/*---------------------------------------------------*/
+static
+void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
+{
+ void* v = malloc ( items * size );
+ return v;
+}
+
+static
+void default_bzfree ( void* opaque, void* addr )
+{
+ if (addr != NULL) free ( addr );
+}
+
+#ifndef BZ_NO_COMPRESS
+/*---------------------------------------------------*/
+static
+void prepare_new_block ( EState* s )
+{
+ Int32 i;
+ s->nblock = 0;
+ s->numZ = 0;
+ s->state_out_pos = 0;
+ BZ_INITIALISE_CRC ( s->blockCRC );
+ for (i = 0; i < 256; i++) s->inUse[i] = False;
+ s->blockNo++;
+}
+
+
+/*---------------------------------------------------*/
+static
+void init_RL ( EState* s )
+{
+ s->state_in_ch = 256;
+ s->state_in_len = 0;
+}
+
+
+static
+Bool isempty_RL ( EState* s )
+{
+ if (s->state_in_ch < 256 && s->state_in_len > 0)
+ return False; else
+ return True;
+}
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressInit)
+ ( bz_stream* strm,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ Int32 n;
+ EState* s;
+
+ if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+ if (strm == NULL ||
+ blockSize100k < 1 || blockSize100k > 9 ||
+ workFactor < 0 || workFactor > 250)
+ return BZ_PARAM_ERROR;
+
+ if (workFactor == 0) workFactor = 30;
+ if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+ if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+ s = BZALLOC( sizeof(EState) );
+ if (s == NULL) return BZ_MEM_ERROR;
+ s->strm = strm;
+
+ s->arr1 = NULL;
+ s->arr2 = NULL;
+ s->ftab = NULL;
+
+ n = 100000 * blockSize100k;
+ s->arr1 = BZALLOC( n * sizeof(UInt32) );
+ s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
+ s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
+
+ if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
+ if (s->arr1 != NULL) BZFREE(s->arr1);
+ if (s->arr2 != NULL) BZFREE(s->arr2);
+ if (s->ftab != NULL) BZFREE(s->ftab);
+ if (s != NULL) BZFREE(s);
+ return BZ_MEM_ERROR;
+ }
+
+ s->blockNo = 0;
+ s->state = BZ_S_INPUT;
+ s->mode = BZ_M_RUNNING;
+ s->combinedCRC = 0;
+ s->blockSize100k = blockSize100k;
+ s->nblockMAX = 100000 * blockSize100k - 19;
+ s->verbosity = verbosity;
+ s->workFactor = workFactor;
+
+ s->block = (UChar*)s->arr2;
+ s->mtfv = (UInt16*)s->arr1;
+ s->zbits = NULL;
+ s->ptr = (UInt32*)s->arr1;
+
+ strm->state = s;
+ strm->total_in_lo32 = 0;
+ strm->total_in_hi32 = 0;
+ strm->total_out_lo32 = 0;
+ strm->total_out_hi32 = 0;
+ init_RL ( s );
+ prepare_new_block ( s );
+ return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void add_pair_to_block ( EState* s )
+{
+ Int32 i;
+ UChar ch = (UChar)(s->state_in_ch);
+ for (i = 0; i < s->state_in_len; i++) {
+ BZ_UPDATE_CRC( s->blockCRC, ch );
+ }
+ s->inUse[s->state_in_ch] = True;
+ switch (s->state_in_len) {
+ case 1:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ case 2:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ case 3:
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ break;
+ default:
+ s->inUse[s->state_in_len-4] = True;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = (UChar)ch; s->nblock++;
+ s->block[s->nblock] = ((UChar)(s->state_in_len-4));
+ s->nblock++;
+ break;
+ }
+}
+
+
+/*---------------------------------------------------*/
+static
+void flush_RL ( EState* s )
+{
+ if (s->state_in_ch < 256) add_pair_to_block ( s );
+ init_RL ( s );
+}
+
+
+/*---------------------------------------------------*/
+#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
+{ \
+ UInt32 zchh = (UInt32)(zchh0); \
+ /*-- fast track the common case --*/ \
+ if (zchh != zs->state_in_ch && \
+ zs->state_in_len == 1) { \
+ UChar ch = (UChar)(zs->state_in_ch); \
+ BZ_UPDATE_CRC( zs->blockCRC, ch ); \
+ zs->inUse[zs->state_in_ch] = True; \
+ zs->block[zs->nblock] = (UChar)ch; \
+ zs->nblock++; \
+ zs->state_in_ch = zchh; \
+ } \
+ else \
+ /*-- general, uncommon cases --*/ \
+ if (zchh != zs->state_in_ch || \
+ zs->state_in_len == 255) { \
+ if (zs->state_in_ch < 256) \
+ add_pair_to_block ( zs ); \
+ zs->state_in_ch = zchh; \
+ zs->state_in_len = 1; \
+ } else { \
+ zs->state_in_len++; \
+ } \
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_input_until_stop ( EState* s )
+{
+ Bool progress_in = False;
+
+ if (s->mode == BZ_M_RUNNING) {
+
+ /*-- fast track the common case --*/
+ while (True) {
+ /*-- block full? --*/
+ if (s->nblock >= s->nblockMAX) break;
+ /*-- no input? --*/
+ if (s->strm->avail_in == 0) break;
+ progress_in = True;
+ ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
+ s->strm->next_in++;
+ s->strm->avail_in--;
+ s->strm->total_in_lo32++;
+ if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+ }
+
+ } else {
+
+ /*-- general, uncommon case --*/
+ while (True) {
+ /*-- block full? --*/
+ if (s->nblock >= s->nblockMAX) break;
+ /*-- no input? --*/
+ if (s->strm->avail_in == 0) break;
+ /*-- flush/finish end? --*/
+ if (s->avail_in_expect == 0) break;
+ progress_in = True;
+ ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
+ s->strm->next_in++;
+ s->strm->avail_in--;
+ s->strm->total_in_lo32++;
+ if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+ s->avail_in_expect--;
+ }
+ }
+ return progress_in;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_output_until_stop ( EState* s )
+{
+ Bool progress_out = False;
+
+ while (True) {
+
+ /*-- no output space? --*/
+ if (s->strm->avail_out == 0) break;
+
+ /*-- block done? --*/
+ if (s->state_out_pos >= s->numZ) break;
+
+ progress_out = True;
+ *(s->strm->next_out) = s->zbits[s->state_out_pos];
+ s->state_out_pos++;
+ s->strm->avail_out--;
+ s->strm->next_out++;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ return progress_out;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool handle_compress ( bz_stream* strm )
+{
+ Bool progress_in = False;
+ Bool progress_out = False;
+ EState* s = strm->state;
+
+ while (True) {
+
+ if (s->state == BZ_S_OUTPUT) {
+ progress_out |= copy_output_until_stop ( s );
+ if (s->state_out_pos < s->numZ) break;
+ if (s->mode == BZ_M_FINISHING &&
+ s->avail_in_expect == 0 &&
+ isempty_RL(s)) break;
+ prepare_new_block ( s );
+ s->state = BZ_S_INPUT;
+ if (s->mode == BZ_M_FLUSHING &&
+ s->avail_in_expect == 0 &&
+ isempty_RL(s)) break;
+ }
+
+ if (s->state == BZ_S_INPUT) {
+ progress_in |= copy_input_until_stop ( s );
+ if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
+ flush_RL ( s );
+ BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
+ s->state = BZ_S_OUTPUT;
+ }
+ else
+ if (s->nblock >= s->nblockMAX) {
+ BZ2_compressBlock ( s, False );
+ s->state = BZ_S_OUTPUT;
+ }
+ else
+ if (s->strm->avail_in == 0) {
+ break;
+ }
+ }
+
+ }
+
+ return progress_in || progress_out;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
+{
+ Bool progress;
+ EState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ preswitch:
+ switch (s->mode) {
+
+ case BZ_M_IDLE:
+ return BZ_SEQUENCE_ERROR;
+
+ case BZ_M_RUNNING:
+ if (action == BZ_RUN) {
+ progress = handle_compress ( strm );
+ return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
+ }
+ else
+ if (action == BZ_FLUSH) {
+ s->avail_in_expect = strm->avail_in;
+ s->mode = BZ_M_FLUSHING;
+ goto preswitch;
+ }
+ else
+ if (action == BZ_FINISH) {
+ s->avail_in_expect = strm->avail_in;
+ s->mode = BZ_M_FINISHING;
+ goto preswitch;
+ }
+ else
+ return BZ_PARAM_ERROR;
+
+ case BZ_M_FLUSHING:
+ if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect != s->strm->avail_in)
+ return BZ_SEQUENCE_ERROR;
+ progress = handle_compress ( strm );
+ if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+ s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
+ s->mode = BZ_M_RUNNING;
+ return BZ_RUN_OK;
+
+ case BZ_M_FINISHING:
+ if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect != s->strm->avail_in)
+ return BZ_SEQUENCE_ERROR;
+ progress = handle_compress ( strm );
+ if (!progress) return BZ_SEQUENCE_ERROR;
+ if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+ s->state_out_pos < s->numZ) return BZ_FINISH_OK;
+ s->mode = BZ_M_IDLE;
+ return BZ_STREAM_END;
+ }
+ return BZ_OK; /*--not reached--*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
+{
+ EState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ if (s->arr1 != NULL) BZFREE(s->arr1);
+ if (s->arr2 != NULL) BZFREE(s->arr2);
+ if (s->ftab != NULL) BZFREE(s->ftab);
+ BZFREE(strm->state);
+
+ strm->state = NULL;
+
+ return BZ_OK;
+}
+#endif /* BZ_NO_COMPRESS */
+
+/*---------------------------------------------------*/
+/*--- Decompression stuff ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressInit)
+ ( bz_stream* strm,
+ int verbosity,
+ int small )
+{
+ DState* s;
+
+ if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ if (small != 0 && small != 1) return BZ_PARAM_ERROR;
+ if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
+
+ if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+ if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+ s = BZALLOC( sizeof(DState) );
+ if (s == NULL) return BZ_MEM_ERROR;
+ s->strm = strm;
+ strm->state = s;
+ s->state = BZ_X_MAGIC_1;
+ s->bsLive = 0;
+ s->bsBuff = 0;
+ s->calculatedCombinedCRC = 0;
+ strm->total_in_lo32 = 0;
+ strm->total_in_hi32 = 0;
+ strm->total_out_lo32 = 0;
+ strm->total_out_hi32 = 0;
+ s->smallDecompress = (Bool)small;
+ s->ll4 = NULL;
+ s->ll16 = NULL;
+ s->tt = NULL;
+ s->currBlockNo = 0;
+ s->verbosity = verbosity;
+
+ return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void unRLE_obuf_to_output_FAST ( DState* s )
+{
+ UChar k1;
+
+ if (s->blockRandomised) {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return;
+
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
+ s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+ }
+
+ } else {
+
+ /* restore */
+ UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
+ UChar c_state_out_ch = s->state_out_ch;
+ Int32 c_state_out_len = s->state_out_len;
+ Int32 c_nblock_used = s->nblock_used;
+ Int32 c_k0 = s->k0;
+ UInt32* c_tt = s->tt;
+ UInt32 c_tPos = s->tPos;
+ char* cs_next_out = s->strm->next_out;
+ unsigned int cs_avail_out = s->strm->avail_out;
+ /* end restore */
+
+ UInt32 avail_out_INIT = cs_avail_out;
+ Int32 s_save_nblockPP = s->save_nblock+1;
+ unsigned int total_out_lo32_old;
+
+ while (True) {
+
+ /* try to finish existing run */
+ if (c_state_out_len > 0) {
+ while (True) {
+ if (cs_avail_out == 0) goto return_notr;
+ if (c_state_out_len == 1) break;
+ *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+ BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+ c_state_out_len--;
+ cs_next_out++;
+ cs_avail_out--;
+ }
+ s_state_out_len_eq_one:
+ {
+ if (cs_avail_out == 0) {
+ c_state_out_len = 1; goto return_notr;
+ };
+ *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+ BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+ cs_next_out++;
+ cs_avail_out--;
+ }
+ }
+ /* can a new run be started? */
+ if (c_nblock_used == s_save_nblockPP) {
+ c_state_out_len = 0; goto return_notr;
+ };
+ c_state_out_ch = c_k0;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (k1 != c_k0) {
+ c_k0 = k1; goto s_state_out_len_eq_one;
+ };
+ if (c_nblock_used == s_save_nblockPP)
+ goto s_state_out_len_eq_one;
+
+ c_state_out_len = 2;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (c_nblock_used == s_save_nblockPP) continue;
+ if (k1 != c_k0) { c_k0 = k1; continue; };
+
+ c_state_out_len = 3;
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ if (c_nblock_used == s_save_nblockPP) continue;
+ if (k1 != c_k0) { c_k0 = k1; continue; };
+
+ BZ_GET_FAST_C(k1); c_nblock_used++;
+ c_state_out_len = ((Int32)k1) + 4;
+ BZ_GET_FAST_C(c_k0); c_nblock_used++;
+ }
+
+ return_notr:
+ total_out_lo32_old = s->strm->total_out_lo32;
+ s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
+ if (s->strm->total_out_lo32 < total_out_lo32_old)
+ s->strm->total_out_hi32++;
+
+ /* save */
+ s->calculatedBlockCRC = c_calculatedBlockCRC;
+ s->state_out_ch = c_state_out_ch;
+ s->state_out_len = c_state_out_len;
+ s->nblock_used = c_nblock_used;
+ s->k0 = c_k0;
+ s->tt = c_tt;
+ s->tPos = c_tPos;
+ s->strm->next_out = cs_next_out;
+ s->strm->avail_out = cs_avail_out;
+ /* end save */
+ }
+}
+
+
+/*---------------------------------------------------*/
+__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
+{
+ Int32 nb, na, mid;
+ nb = 0;
+ na = 256;
+ do {
+ mid = (nb + na) >> 1;
+ if (indx >= cftab[mid]) nb = mid; else na = mid;
+ }
+ while (na - nb != 1);
+ return nb;
+}
+
+
+/*---------------------------------------------------*/
+static
+void unRLE_obuf_to_output_SMALL ( DState* s )
+{
+ UChar k1;
+
+ if (s->blockRandomised) {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return;
+
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
+ k1 ^= BZ_RAND_MASK; s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
+ s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+ }
+
+ } else {
+
+ while (True) {
+ /* try to finish existing run */
+ while (True) {
+ if (s->strm->avail_out == 0) return;
+ if (s->state_out_len == 0) break;
+ *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+ BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+ s->state_out_len--;
+ s->strm->next_out++;
+ s->strm->avail_out--;
+ s->strm->total_out_lo32++;
+ if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+ }
+
+ /* can a new run be started? */
+ if (s->nblock_used == s->save_nblock+1) return;
+
+ s->state_out_len = 1;
+ s->state_out_ch = s->k0;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 2;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ s->state_out_len = 3;
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ if (s->nblock_used == s->save_nblock+1) continue;
+ if (k1 != s->k0) { s->k0 = k1; continue; };
+
+ BZ_GET_SMALL(k1); s->nblock_used++;
+ s->state_out_len = ((Int32)k1) + 4;
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ }
+
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
+{
+ DState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ while (True) {
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
+ if (s->state == BZ_X_OUTPUT) {
+ if (s->smallDecompress)
+ unRLE_obuf_to_output_SMALL ( s ); else
+ unRLE_obuf_to_output_FAST ( s );
+ if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
+ BZ_FINALISE_CRC ( s->calculatedBlockCRC );
+ if (s->verbosity >= 3)
+ VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
+ s->calculatedBlockCRC );
+ if (s->verbosity >= 2) VPrintf0 ( "]" );
+ if (s->calculatedBlockCRC != s->storedBlockCRC)
+ return BZ_DATA_ERROR;
+ s->calculatedCombinedCRC
+ = (s->calculatedCombinedCRC << 1) |
+ (s->calculatedCombinedCRC >> 31);
+ s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
+ s->state = BZ_X_BLKHDR_1;
+ } else {
+ return BZ_OK;
+ }
+ }
+ if (s->state >= BZ_X_MAGIC_1) {
+ Int32 r = BZ2_decompress ( s );
+ if (r == BZ_STREAM_END) {
+ if (s->verbosity >= 3)
+ VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
+ s->storedCombinedCRC, s->calculatedCombinedCRC );
+ if (s->calculatedCombinedCRC != s->storedCombinedCRC)
+ return BZ_DATA_ERROR;
+ return r;
+ }
+ if (s->state != BZ_X_OUTPUT) return r;
+ }
+ }
+
+ AssertH ( 0, 6001 );
+
+ return 0; /*NOTREACHED*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
+{
+ DState* s;
+ if (strm == NULL) return BZ_PARAM_ERROR;
+ s = strm->state;
+ if (s == NULL) return BZ_PARAM_ERROR;
+ if (s->strm != strm) return BZ_PARAM_ERROR;
+
+ if (s->tt != NULL) BZFREE(s->tt);
+ if (s->ll16 != NULL) BZFREE(s->ll16);
+ if (s->ll4 != NULL) BZFREE(s->ll4);
+
+ BZFREE(strm->state);
+ strm->state = NULL;
+
+ return BZ_OK;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+/*--- File I/O stuff ---*/
+/*---------------------------------------------------*/
+
+#define BZ_SETERR(eee) \
+{ \
+ if (bzerror != NULL) *bzerror = eee; \
+ if (bzf != NULL) bzf->lastErr = eee; \
+}
+
+typedef
+ struct {
+ FILE* handle;
+ Char buf[BZ_MAX_UNUSED];
+ Int32 bufN;
+ Bool writing;
+ bz_stream strm;
+ Int32 lastErr;
+ Bool initialisedOk;
+ }
+ bzFile;
+
+
+/*---------------------------------------------*/
+static Bool myfeof ( FILE* f )
+{
+ Int32 c = fgetc ( f );
+ if (c == EOF) return True;
+ ungetc ( c, f );
+ return False;
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzWriteOpen)
+ ( int* bzerror,
+ FILE* f,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ Int32 ret;
+ bzFile* bzf = NULL;
+
+ BZ_SETERR(BZ_OK);
+
+ if (f == NULL ||
+ (blockSize100k < 1 || blockSize100k > 9) ||
+ (workFactor < 0 || workFactor > 250) ||
+ (verbosity < 0 || verbosity > 4))
+ { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+ if (ferror(f))
+ { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+ bzf = malloc ( sizeof(bzFile) );
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+ BZ_SETERR(BZ_OK);
+ bzf->initialisedOk = False;
+ bzf->bufN = 0;
+ bzf->handle = f;
+ bzf->writing = True;
+ bzf->strm.bzalloc = NULL;
+ bzf->strm.bzfree = NULL;
+ bzf->strm.opaque = NULL;
+
+ if (workFactor == 0) workFactor = 30;
+ ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
+ verbosity, workFactor );
+ if (ret != BZ_OK)
+ { BZ_SETERR(ret); free(bzf); return NULL; };
+
+ bzf->strm.avail_in = 0;
+ bzf->initialisedOk = True;
+ return bzf;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWrite)
+ ( int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len )
+{
+ Int32 n, n2, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+ if (bzf == NULL || buf == NULL || len < 0)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+ if (!(bzf->writing))
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+
+ if (len == 0)
+ { BZ_SETERR(BZ_OK); return; };
+
+ bzf->strm.avail_in = len;
+ bzf->strm.next_in = buf;
+
+ while (True) {
+ bzf->strm.avail_out = BZ_MAX_UNUSED;
+ bzf->strm.next_out = bzf->buf;
+ ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
+ if (ret != BZ_RUN_OK)
+ { BZ_SETERR(ret); return; };
+
+ if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+ n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+ n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
+ n, bzf->handle );
+ if (n != n2 || ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (bzf->strm.avail_in == 0)
+ { BZ_SETERR(BZ_OK); return; };
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWriteClose)
+ ( int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in,
+ unsigned int* nbytes_out )
+{
+ BZ2_bzWriteClose64 ( bzerror, b, abandon,
+ nbytes_in, NULL, nbytes_out, NULL );
+}
+
+
+void BZ_API(BZ2_bzWriteClose64)
+ ( int* bzerror,
+ BZFILE* b,
+ int abandon,
+ unsigned int* nbytes_in_lo32,
+ unsigned int* nbytes_in_hi32,
+ unsigned int* nbytes_out_lo32,
+ unsigned int* nbytes_out_hi32 )
+{
+ Int32 n, n2, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_OK); return; };
+ if (!(bzf->writing))
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+
+ if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
+ if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
+ if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
+ if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
+
+ if ((!abandon) && bzf->lastErr == BZ_OK) {
+ while (True) {
+ bzf->strm.avail_out = BZ_MAX_UNUSED;
+ bzf->strm.next_out = bzf->buf;
+ ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
+ if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
+ { BZ_SETERR(ret); return; };
+
+ if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+ n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+ n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
+ n, bzf->handle );
+ if (n != n2 || ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (ret == BZ_STREAM_END) break;
+ }
+ }
+
+ if ( !abandon && !ferror ( bzf->handle ) ) {
+ fflush ( bzf->handle );
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return; };
+ }
+
+ if (nbytes_in_lo32 != NULL)
+ *nbytes_in_lo32 = bzf->strm.total_in_lo32;
+ if (nbytes_in_hi32 != NULL)
+ *nbytes_in_hi32 = bzf->strm.total_in_hi32;
+ if (nbytes_out_lo32 != NULL)
+ *nbytes_out_lo32 = bzf->strm.total_out_lo32;
+ if (nbytes_out_hi32 != NULL)
+ *nbytes_out_hi32 = bzf->strm.total_out_hi32;
+
+ BZ_SETERR(BZ_OK);
+ BZ2_bzCompressEnd ( &(bzf->strm) );
+ free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzReadOpen)
+ ( int* bzerror,
+ FILE* f,
+ int verbosity,
+ int small,
+ void* unused,
+ int nUnused )
+{
+ bzFile* bzf = NULL;
+ int ret;
+
+ BZ_SETERR(BZ_OK);
+
+ if (f == NULL ||
+ (small != 0 && small != 1) ||
+ (verbosity < 0 || verbosity > 4) ||
+ (unused == NULL && nUnused != 0) ||
+ (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
+ { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+ if (ferror(f))
+ { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+ bzf = malloc ( sizeof(bzFile) );
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+ BZ_SETERR(BZ_OK);
+
+ bzf->initialisedOk = False;
+ bzf->handle = f;
+ bzf->bufN = 0;
+ bzf->writing = False;
+ bzf->strm.bzalloc = NULL;
+ bzf->strm.bzfree = NULL;
+ bzf->strm.opaque = NULL;
+
+ while (nUnused > 0) {
+ bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
+ unused = ((void*)( 1 + ((UChar*)(unused)) ));
+ nUnused--;
+ }
+
+ ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
+ if (ret != BZ_OK)
+ { BZ_SETERR(ret); free(bzf); return NULL; };
+
+ bzf->strm.avail_in = bzf->bufN;
+ bzf->strm.next_in = bzf->buf;
+
+ bzf->initialisedOk = True;
+ return bzf;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
+{
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_OK); return; };
+
+ if (bzf->writing)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+
+ if (bzf->initialisedOk)
+ (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
+ free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzRead)
+ ( int* bzerror,
+ BZFILE* b,
+ void* buf,
+ int len )
+{
+ Int32 n, ret;
+ bzFile* bzf = (bzFile*)b;
+
+ BZ_SETERR(BZ_OK);
+
+ if (bzf == NULL || buf == NULL || len < 0)
+ { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
+
+ if (bzf->writing)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
+
+ if (len == 0)
+ { BZ_SETERR(BZ_OK); return 0; };
+
+ bzf->strm.avail_out = len;
+ bzf->strm.next_out = buf;
+
+ while (True) {
+
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return 0; };
+
+ if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
+ n = fread ( bzf->buf, sizeof(UChar),
+ BZ_MAX_UNUSED, bzf->handle );
+ if (ferror(bzf->handle))
+ { BZ_SETERR(BZ_IO_ERROR); return 0; };
+ bzf->bufN = n;
+ bzf->strm.avail_in = bzf->bufN;
+ bzf->strm.next_in = bzf->buf;
+ }
+
+ ret = BZ2_bzDecompress ( &(bzf->strm) );
+
+ if (ret != BZ_OK && ret != BZ_STREAM_END)
+ { BZ_SETERR(ret); return 0; };
+
+ if (ret == BZ_OK && myfeof(bzf->handle) &&
+ bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
+ { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
+
+ if (ret == BZ_STREAM_END)
+ { BZ_SETERR(BZ_STREAM_END);
+ return len - bzf->strm.avail_out; };
+ if (bzf->strm.avail_out == 0)
+ { BZ_SETERR(BZ_OK); return len; };
+
+ }
+
+ return 0; /*not reached*/
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadGetUnused)
+ ( int* bzerror,
+ BZFILE* b,
+ void** unused,
+ int* nUnused )
+{
+ bzFile* bzf = (bzFile*)b;
+ if (bzf == NULL)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+ if (bzf->lastErr != BZ_STREAM_END)
+ { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+ if (unused == NULL || nUnused == NULL)
+ { BZ_SETERR(BZ_PARAM_ERROR); return; };
+
+ BZ_SETERR(BZ_OK);
+ *nUnused = bzf->strm.avail_in;
+ *unused = bzf->strm.next_in;
+}
+#endif
+
+
+/*---------------------------------------------------*/
+/*--- Misc convenience stuff ---*/
+/*---------------------------------------------------*/
+#ifndef BZ_NO_COMPRESS
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffCompress)
+ ( char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int blockSize100k,
+ int verbosity,
+ int workFactor )
+{
+ bz_stream strm;
+ int ret;
+
+ if (dest == NULL || destLen == NULL ||
+ source == NULL ||
+ blockSize100k < 1 || blockSize100k > 9 ||
+ verbosity < 0 || verbosity > 4 ||
+ workFactor < 0 || workFactor > 250)
+ return BZ_PARAM_ERROR;
+
+ if (workFactor == 0) workFactor = 30;
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+ strm.opaque = NULL;
+ ret = BZ2_bzCompressInit ( &strm, blockSize100k,
+ verbosity, workFactor );
+ if (ret != BZ_OK) return ret;
+
+ strm.next_in = source;
+ strm.next_out = dest;
+ strm.avail_in = sourceLen;
+ strm.avail_out = *destLen;
+
+ ret = BZ2_bzCompress ( &strm, BZ_FINISH );
+ if (ret == BZ_FINISH_OK) goto output_overflow;
+ if (ret != BZ_STREAM_END) goto errhandler;
+
+ /* normal termination */
+ *destLen -= strm.avail_out;
+ BZ2_bzCompressEnd ( &strm );
+ return BZ_OK;
+
+ output_overflow:
+ BZ2_bzCompressEnd ( &strm );
+ return BZ_OUTBUFF_FULL;
+
+ errhandler:
+ BZ2_bzCompressEnd ( &strm );
+ return ret;
+}
+#endif /* BZ_NO_COMPRESS */
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffDecompress)
+ ( char* dest,
+ unsigned int* destLen,
+ char* source,
+ unsigned int sourceLen,
+ int small,
+ int verbosity )
+{
+ bz_stream strm;
+ int ret;
+
+ if (destLen == NULL || source == NULL)
+ return BZ_PARAM_ERROR;
+
+ strm.bzalloc = NULL;
+ strm.bzfree = NULL;
+ strm.opaque = NULL;
+ ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
+ if (ret != BZ_OK) return ret;
+
+ strm.next_in = source;
+ strm.next_out = dest;
+ strm.avail_in = sourceLen;
+ strm.avail_out = *destLen;
+
+ ret = BZ2_bzDecompress ( &strm );
+ *destLen -= strm.avail_out;
+ if (ret == BZ_OK) goto output_overflow_or_eof;
+ if (ret != BZ_STREAM_END) goto errhandler;
+
+ /* normal termination */
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_OK;
+
+ output_overflow_or_eof:
+ if (strm.avail_out > 0) {
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_UNEXPECTED_EOF;
+ } else {
+ BZ2_bzDecompressEnd ( &strm );
+ return BZ_OUTBUFF_FULL;
+ };
+
+ errhandler:
+ BZ2_bzDecompressEnd ( &strm );
+ return ret;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ Code contributed by Yoshioka Tsuneo
+ (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
+ to support better zlib compatibility.
+ This code is not _officially_ part of libbzip2 (yet);
+ I haven't tested it, documented it, or considered the
+ threading-safeness of it.
+ If this code breaks, please contact both Yoshioka and me.
+--*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+/*--
+ return version like "0.9.0c".
+--*/
+const char * BZ_API(BZ2_bzlibVersion)(void)
+{
+ return BZ_VERSION;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+static
+BZFILE * bzopen_or_bzdopen
+ ( const char *path, /* no use when bzdopen */
+ int fd, /* no use when bzdopen */
+ const char *mode,
+ int open_mode) /* bzopen: 0, bzdopen:1 */
+{
+ int bzerr;
+ char unused[BZ_MAX_UNUSED];
+ int blockSize100k = 9;
+ int writing = 0;
+ char mode2[10] = "";
+ FILE *fp = NULL;
+ BZFILE *bzfp = NULL;
+ int verbosity = 0;
+ int workFactor = 30;
+ int smallMode = 0;
+ int nUnused = 0;
+
+ if (mode == NULL) return NULL;
+ while (*mode) {
+ switch (*mode) {
+ case 'r':
+ writing = 0; break;
+ case 'w':
+ writing = 1; break;
+ case 's':
+ smallMode = 1; break;
+ default:
+ if (isdigit((int)(*mode))) {
+ blockSize100k = *mode-BZ_HDR_0;
+ }
+ }
+ mode++;
+ }
+ strcat(mode2, writing ? "w" : "r" );
+ strcat(mode2,"b"); /* binary mode */
+
+ if (open_mode==0) {
+ if (path==NULL || strcmp(path,"")==0) {
+ fp = (writing ? stdout : stdin);
+ SET_BINARY_MODE(fp);
+ } else {
+ fp = fopen(path,mode2);
+ }
+ } else {
+#ifdef BZ_STRICT_ANSI
+ fp = NULL;
+#else
+ fp = fdopen(fd,mode2);
+#endif
+ }
+ if (fp == NULL) return NULL;
+
+ if (writing) {
+ /* Guard against total chaos and anarchy -- JRS */
+ if (blockSize100k < 1) blockSize100k = 1;
+ if (blockSize100k > 9) blockSize100k = 9;
+ bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
+ verbosity,workFactor);
+ } else {
+ bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
+ unused,nUnused);
+ }
+ if (bzfp == NULL) {
+ if (fp != stdin && fp != stdout) fclose(fp);
+ return NULL;
+ }
+ return bzfp;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ open file for read or write.
+ ex) bzopen("file","w9")
+ case path="" or NULL => use stdin or stdout.
+--*/
+BZFILE * BZ_API(BZ2_bzopen)
+ ( const char *path,
+ const char *mode )
+{
+ return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
+}
+
+
+/*---------------------------------------------------*/
+BZFILE * BZ_API(BZ2_bzdopen)
+ ( int fd,
+ const char *mode )
+{
+ return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
+{
+ int bzerr, nread;
+ if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
+ nread = BZ2_bzRead(&bzerr,b,buf,len);
+ if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
+ return nread;
+ } else {
+ return -1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
+{
+ int bzerr;
+
+ BZ2_bzWrite(&bzerr,b,buf,len);
+ if(bzerr == BZ_OK){
+ return len;
+ }else{
+ return -1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzflush) (BZFILE *b)
+{
+ /* do nothing now... */
+ return 0;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzclose) (BZFILE* b)
+{
+ int bzerr;
+ FILE *fp = ((bzFile *)b)->handle;
+
+ if (b==NULL) {return;}
+ if(((bzFile*)b)->writing){
+ BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
+ if(bzerr != BZ_OK){
+ BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
+ }
+ }else{
+ BZ2_bzReadClose(&bzerr,b);
+ }
+ if(fp!=stdin && fp!=stdout){
+ fclose(fp);
+ }
+}
+
+
+/*---------------------------------------------------*/
+/*--
+ return last error code
+--*/
+static char *bzerrorstrings[] = {
+ "OK"
+ ,"SEQUENCE_ERROR"
+ ,"PARAM_ERROR"
+ ,"MEM_ERROR"
+ ,"DATA_ERROR"
+ ,"DATA_ERROR_MAGIC"
+ ,"IO_ERROR"
+ ,"UNEXPECTED_EOF"
+ ,"OUTBUFF_FULL"
+ ,"CONFIG_ERROR"
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+ ,"???" /* for future */
+};
+
+
+const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
+{
+ int err = ((bzFile *)b)->lastErr;
+
+ if(err>0) err = 0;
+ *errnum = err;
+ return bzerrorstrings[err*-1];
+}
+#endif
+
+void bz_internal_error(int errcode)
+{
+ printf ("BZIP2 internal error %d\n", errcode);
+}
+
+/*-------------------------------------------------------------*/
+/*--- end bzlib.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_blocksort.c b/lib/bzip2/bzlib_blocksort.c
new file mode 100644
index 00000000..27855215
--- /dev/null
+++ b/lib/bzip2/bzlib_blocksort.c
@@ -0,0 +1,1134 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery ---*/
+/*--- blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0.6 of 6 September 2010
+ Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting ---*/
+/*--- algorithm, for repetitive blocks ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+void fallbackSimpleSort ( UInt32* fmap,
+ UInt32* eclass,
+ Int32 lo,
+ Int32 hi )
+{
+ Int32 i, j, tmp;
+ UInt32 ec_tmp;
+
+ if (lo == hi) return;
+
+ if (hi - lo > 3) {
+ for ( i = hi-4; i >= lo; i-- ) {
+ tmp = fmap[i];
+ ec_tmp = eclass[tmp];
+ for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+ fmap[j-4] = fmap[j];
+ fmap[j-4] = tmp;
+ }
+ }
+
+ for ( i = hi-1; i >= lo; i-- ) {
+ tmp = fmap[i];
+ ec_tmp = eclass[tmp];
+ for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+ fmap[j-1] = fmap[j];
+ fmap[j-1] = tmp;
+ }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn) \
+{ \
+ Int32 yyp1 = (zzp1); \
+ Int32 yyp2 = (zzp2); \
+ Int32 yyn = (zzn); \
+ while (yyn > 0) { \
+ fswap(fmap[yyp1], fmap[yyp2]); \
+ yyp1++; yyp2++; yyn--; \
+ } \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+ stackHi[sp] = hz; \
+ sp++; }
+
+#define fpop(lz,hz) { sp--; \
+ lz = stackLo[sp]; \
+ hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE 100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap,
+ UInt32* eclass,
+ Int32 loSt,
+ Int32 hiSt )
+{
+ Int32 unLo, unHi, ltLo, gtHi, n, m;
+ Int32 sp, lo, hi;
+ UInt32 med, r, r3;
+ Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+ Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+ r = 0;
+
+ sp = 0;
+ fpush ( loSt, hiSt );
+
+ while (sp > 0) {
+
+ AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
+
+ fpop ( lo, hi );
+ if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+ fallbackSimpleSort ( fmap, eclass, lo, hi );
+ continue;
+ }
+
+ /* Random partitioning. Median of 3 sometimes fails to
+ avoid bad cases. Median of 9 seems to help but
+ looks rather expensive. This too seems to work but
+ is cheaper. Guidance for the magic constants
+ 7621 and 32768 is taken from Sedgewick's algorithms
+ book, chapter 35.
+ */
+ r = ((r * 7621) + 1) % 32768;
+ r3 = r % 3;
+ if (r3 == 0) med = eclass[fmap[lo]]; else
+ if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+ med = eclass[fmap[hi]];
+
+ unLo = ltLo = lo;
+ unHi = gtHi = hi;
+
+ while (1) {
+ while (1) {
+ if (unLo > unHi) break;
+ n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+ if (n == 0) {
+ fswap(fmap[unLo], fmap[ltLo]);
+ ltLo++; unLo++;
+ continue;
+ };
+ if (n > 0) break;
+ unLo++;
+ }
+ while (1) {
+ if (unLo > unHi) break;
+ n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+ if (n == 0) {
+ fswap(fmap[unHi], fmap[gtHi]);
+ gtHi--; unHi--;
+ continue;
+ };
+ if (n < 0) break;
+ unHi--;
+ }
+ if (unLo > unHi) break;
+ fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+ }
+
+ AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+ if (gtHi < ltLo) continue;
+
+ n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+ m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - (gtHi - unHi) + 1;
+
+ if (n - lo > hi - m) {
+ fpush ( lo, n );
+ fpush ( m, hi );
+ } else {
+ fpush ( m, hi );
+ fpush ( lo, n );
+ }
+ }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > 0
+ eclass exists for [0 .. nblock-1]
+ ((UChar*)eclass) [0 .. nblock-1] holds block
+ ptr exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)eclass) [0 .. nblock-1] holds block
+ All other areas of eclass destroyed
+ fmap [0 .. nblock-1] holds sorted order
+ bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define WORD_BH(zz) bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz) ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap,
+ UInt32* eclass,
+ UInt32* bhtab,
+ Int32 nblock,
+ Int32 verb )
+{
+ Int32 ftab[257];
+ Int32 ftabCopy[256];
+ Int32 H, i, j, k, l, r, cc, cc1;
+ Int32 nNotDone;
+ Int32 nBhtab;
+ UChar* eclass8 = (UChar*)eclass;
+
+ /*--
+ Initial 1-char radix sort to generate
+ initial fmap and initial BH bits.
+ --*/
+ if (verb >= 4)
+ VPrintf0 ( " bucket sorting ...\n" );
+ for (i = 0; i < 257; i++) ftab[i] = 0;
+ for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+ for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i];
+ for (i = 1; i < 257; i++) ftab[i] += ftab[i-1];
+
+ for (i = 0; i < nblock; i++) {
+ j = eclass8[i];
+ k = ftab[j] - 1;
+ ftab[j] = k;
+ fmap[k] = i;
+ }
+
+ nBhtab = 2 + (nblock / 32);
+ for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+ for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+ /*--
+ Inductively refine the buckets. Kind-of an
+ "exponential radix sort" (!), inspired by the
+ Manber-Myers suffix array construction algorithm.
+ --*/
+
+ /*-- set sentinel bits for block-end detection --*/
+ for (i = 0; i < 32; i++) {
+ SET_BH(nblock + 2*i);
+ CLEAR_BH(nblock + 2*i + 1);
+ }
+
+ /*-- the log(N) loop --*/
+ H = 1;
+ while (1) {
+
+ if (verb >= 4)
+ VPrintf1 ( " depth %6d has ", H );
+
+ j = 0;
+ for (i = 0; i < nblock; i++) {
+ if (ISSET_BH(i)) j = i;
+ k = fmap[i] - H; if (k < 0) k += nblock;
+ eclass[k] = j;
+ }
+
+ nNotDone = 0;
+ r = -1;
+ while (1) {
+
+ /*-- find the next non-singleton bucket --*/
+ k = r + 1;
+ while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+ if (ISSET_BH(k)) {
+ while (WORD_BH(k) == 0xffffffff) k += 32;
+ while (ISSET_BH(k)) k++;
+ }
+ l = k - 1;
+ if (l >= nblock) break;
+ while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+ if (!ISSET_BH(k)) {
+ while (WORD_BH(k) == 0x00000000) k += 32;
+ while (!ISSET_BH(k)) k++;
+ }
+ r = k - 1;
+ if (r >= nblock) break;
+
+ /*-- now [l, r] bracket current bucket --*/
+ if (r > l) {
+ nNotDone += (r - l + 1);
+ fallbackQSort3 ( fmap, eclass, l, r );
+
+ /*-- scan bucket and generate header bits-- */
+ cc = -1;
+ for (i = l; i <= r; i++) {
+ cc1 = eclass[fmap[i]];
+ if (cc != cc1) { SET_BH(i); cc = cc1; };
+ }
+ }
+ }
+
+ if (verb >= 4)
+ VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+ H *= 2;
+ if (H > nblock || nNotDone == 0) break;
+ }
+
+ /*--
+ Reconstruct the original block in
+ eclass8 [0 .. nblock-1], since the
+ previous phase destroyed it.
+ --*/
+ if (verb >= 4)
+ VPrintf0 ( " reconstructing block ...\n" );
+ j = 0;
+ for (i = 0; i < nblock; i++) {
+ while (ftabCopy[j] == 0) j++;
+ ftabCopy[j]--;
+ eclass8[fmap[i]] = (UChar)j;
+ }
+ AssertH ( j < 256, 1005 );
+}
+
+#undef SET_BH
+#undef CLEAR_BH
+#undef ISSET_BH
+#undef WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting ---*/
+/*--- algorithm. Faster for "normal" ---*/
+/*--- non-repetitive blocks. ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32 i1,
+ UInt32 i2,
+ UChar* block,
+ UInt16* quadrant,
+ UInt32 nblock,
+ Int32* budget )
+{
+ Int32 k;
+ UChar c1, c2;
+ UInt16 s1, s2;
+
+ AssertD ( i1 != i2, "mainGtU" );
+ /* 1 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 2 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 3 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 4 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 5 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 6 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 7 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 8 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 9 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 10 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 11 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+ /* 12 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ i1++; i2++;
+
+ k = nblock + 8;
+
+ do {
+ /* 1 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 2 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 3 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 4 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 5 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 6 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 7 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+ /* 8 */
+ c1 = block[i1]; c2 = block[i2];
+ if (c1 != c2) return (c1 > c2);
+ s1 = quadrant[i1]; s2 = quadrant[i2];
+ if (s1 != s2) return (s1 > s2);
+ i1++; i2++;
+
+ if (i1 >= nblock) i1 -= nblock;
+ if (i2 >= nblock) i2 -= nblock;
+
+ k -= 8;
+ (*budget)--;
+ }
+ while (k >= 0);
+
+ return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+ Knuth's increments seem to work better
+ than Incerpi-Sedgewick here. Possibly
+ because the number of elems to sort is
+ usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+ 9841, 29524, 88573, 265720,
+ 797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ Int32 nblock,
+ Int32 lo,
+ Int32 hi,
+ Int32 d,
+ Int32* budget )
+{
+ Int32 i, j, h, bigN, hp;
+ UInt32 v;
+
+ bigN = hi - lo + 1;
+ if (bigN < 2) return;
+
+ hp = 0;
+ while (incs[hp] < bigN) hp++;
+ hp--;
+
+ for (; hp >= 0; hp--) {
+ h = incs[hp];
+
+ i = lo + h;
+ while (True) {
+
+ /*-- copy 1 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ /*-- copy 2 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ /*-- copy 3 --*/
+ if (i > hi) break;
+ v = ptr[i];
+ j = i;
+ while ( mainGtU (
+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget
+ ) ) {
+ ptr[j] = ptr[j-h];
+ j = j - h;
+ if (j <= (lo + h - 1)) break;
+ }
+ ptr[j] = v;
+ i++;
+
+ if (*budget < 0) return;
+ }
+ }
+}
+
+
+/*---------------------------------------------*/
+/*--
+ The following is an implementation of
+ an elegant 3-way quicksort for strings,
+ described in a paper "Fast Algorithms for
+ Sorting and Searching Strings", by Robert
+ Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn) \
+{ \
+ Int32 yyp1 = (zzp1); \
+ Int32 yyp2 = (zzp2); \
+ Int32 yyn = (zzn); \
+ while (yyn > 0) { \
+ mswap(ptr[yyp1], ptr[yyp2]); \
+ yyp1++; yyp2++; yyn--; \
+ } \
+}
+
+static
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+ UChar t;
+ if (a > b) { t = a; a = b; b = t; };
+ if (b > c) {
+ b = c;
+ if (a > b) b = a;
+ }
+ return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+ stackHi[sp] = hz; \
+ stackD [sp] = dz; \
+ sp++; }
+
+#define mpop(lz,hz,dz) { sp--; \
+ lz = stackLo[sp]; \
+ hz = stackHi[sp]; \
+ dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz) \
+ { Int32 tz; \
+ tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+ tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+ tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ Int32 nblock,
+ Int32 loSt,
+ Int32 hiSt,
+ Int32 dSt,
+ Int32* budget )
+{
+ Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+ Int32 sp, lo, hi, d;
+
+ Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+ Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+ Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+ Int32 nextLo[3];
+ Int32 nextHi[3];
+ Int32 nextD [3];
+
+ sp = 0;
+ mpush ( loSt, hiSt, dSt );
+
+ while (sp > 0) {
+
+ AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
+
+ mpop ( lo, hi, d );
+ if (hi - lo < MAIN_QSORT_SMALL_THRESH ||
+ d > MAIN_QSORT_DEPTH_THRESH) {
+ mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+ if (*budget < 0) return;
+ continue;
+ }
+
+ med = (Int32)
+ mmed3 ( block[ptr[ lo ]+d],
+ block[ptr[ hi ]+d],
+ block[ptr[ (lo+hi)>>1 ]+d] );
+
+ unLo = ltLo = lo;
+ unHi = gtHi = hi;
+
+ while (True) {
+ while (True) {
+ if (unLo > unHi) break;
+ n = ((Int32)block[ptr[unLo]+d]) - med;
+ if (n == 0) {
+ mswap(ptr[unLo], ptr[ltLo]);
+ ltLo++; unLo++; continue;
+ };
+ if (n > 0) break;
+ unLo++;
+ }
+ while (True) {
+ if (unLo > unHi) break;
+ n = ((Int32)block[ptr[unHi]+d]) - med;
+ if (n == 0) {
+ mswap(ptr[unHi], ptr[gtHi]);
+ gtHi--; unHi--; continue;
+ };
+ if (n < 0) break;
+ unHi--;
+ }
+ if (unLo > unHi) break;
+ mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+ }
+
+ AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+ if (gtHi < ltLo) {
+ mpush(lo, hi, d+1 );
+ continue;
+ }
+
+ n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+ m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - (gtHi - unHi) + 1;
+
+ nextLo[0] = lo; nextHi[0] = n; nextD[0] = d;
+ nextLo[1] = m; nextHi[1] = hi; nextD[1] = d;
+ nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+ if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+ AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+ AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+ mpush (nextLo[0], nextHi[0], nextD[0]);
+ mpush (nextLo[1], nextHi[1], nextD[1]);
+ mpush (nextLo[2], nextHi[2], nextD[2]);
+ }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > N_OVERSHOOT
+ block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+ ((UChar*)block32) [0 .. nblock-1] holds block
+ ptr exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)block32) [0 .. nblock-1] holds block
+ All other areas of block32 destroyed
+ ftab [0 .. 65536 ] destroyed
+ ptr [0 .. nblock-1] holds sorted order
+ if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr,
+ UChar* block,
+ UInt16* quadrant,
+ UInt32* ftab,
+ Int32 nblock,
+ Int32 verb,
+ Int32* budget )
+{
+ Int32 i, j, k, ss, sb;
+ Int32 runningOrder[256];
+ Bool bigDone[256];
+ Int32 copyStart[256];
+ Int32 copyEnd [256];
+ UChar c1;
+ Int32 numQSorted;
+ UInt16 s;
+ if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" );
+
+ /*-- set up the 2-byte frequency table --*/
+ for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+ j = block[0] << 8;
+ i = nblock-1;
+ for (; i >= 3; i -= 4) {
+ quadrant[i] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+ ftab[j]++;
+ quadrant[i-1] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+ ftab[j]++;
+ quadrant[i-2] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+ ftab[j]++;
+ quadrant[i-3] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+ ftab[j]++;
+ }
+ for (; i >= 0; i--) {
+ quadrant[i] = 0;
+ j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+ ftab[j]++;
+ }
+
+ /*-- (emphasises close relationship of block & quadrant) --*/
+ for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+ block [nblock+i] = block[i];
+ quadrant[nblock+i] = 0;
+ }
+
+ if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" );
+
+ /*-- Complete the initial radix sort --*/
+ for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+ s = block[0] << 8;
+ i = nblock-1;
+ for (; i >= 3; i -= 4) {
+ s = (s >> 8) | (block[i] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i;
+ s = (s >> 8) | (block[i-1] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-1;
+ s = (s >> 8) | (block[i-2] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-2;
+ s = (s >> 8) | (block[i-3] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i-3;
+ }
+ for (; i >= 0; i--) {
+ s = (s >> 8) | (block[i] << 8);
+ j = ftab[s] -1;
+ ftab[s] = j;
+ ptr[j] = i;
+ }
+
+ /*--
+ Now ftab contains the first loc of every small bucket.
+ Calculate the running order, from smallest to largest
+ big bucket.
+ --*/
+ for (i = 0; i <= 255; i++) {
+ bigDone [i] = False;
+ runningOrder[i] = i;
+ }
+
+ {
+ Int32 vv;
+ Int32 h = 1;
+ do h = 3 * h + 1; while (h <= 256);
+ do {
+ h = h / 3;
+ for (i = h; i <= 255; i++) {
+ vv = runningOrder[i];
+ j = i;
+ while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+ runningOrder[j] = runningOrder[j-h];
+ j = j - h;
+ if (j <= (h - 1)) goto zero;
+ }
+ zero:
+ runningOrder[j] = vv;
+ }
+ } while (h != 1);
+ }
+
+ /*--
+ The main sorting loop.
+ --*/
+
+ numQSorted = 0;
+
+ for (i = 0; i <= 255; i++) {
+
+ /*--
+ Process big buckets, starting with the least full.
+ Basically this is a 3-step process in which we call
+ mainQSort3 to sort the small buckets [ss, j], but
+ also make a big effort to avoid the calls if we can.
+ --*/
+ ss = runningOrder[i];
+
+ /*--
+ Step 1:
+ Complete the big bucket [ss] by quicksorting
+ any unsorted small buckets [ss, j], for j != ss.
+ Hopefully previous pointer-scanning phases have already
+ completed many of the small buckets [ss, j], so
+ we don't have to sort them at all.
+ --*/
+ for (j = 0; j <= 255; j++) {
+ if (j != ss) {
+ sb = (ss << 8) + j;
+ if ( ! (ftab[sb] & SETMASK) ) {
+ Int32 lo = ftab[sb] & CLEARMASK;
+ Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+ if (hi > lo) {
+ if (verb >= 4)
+ VPrintf4 ( " qsort [0x%x, 0x%x] "
+ "done %d this %d\n",
+ ss, j, numQSorted, hi - lo + 1 );
+ mainQSort3 (
+ ptr, block, quadrant, nblock,
+ lo, hi, BZ_N_RADIX, budget
+ );
+ numQSorted += (hi - lo + 1);
+ if (*budget < 0) return;
+ }
+ }
+ ftab[sb] |= SETMASK;
+ }
+ }
+
+ AssertH ( !bigDone[ss], 1006 );
+
+ /*--
+ Step 2:
+ Now scan this big bucket [ss] so as to synthesise the
+ sorted order for small buckets [t, ss] for all t,
+ including, magically, the bucket [ss,ss] too.
+ This will avoid doing Real Work in subsequent Step 1's.
+ --*/
+ {
+ for (j = 0; j <= 255; j++) {
+ copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK;
+ copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+ }
+ for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+ k = ptr[j]-1; if (k < 0) k += nblock;
+ c1 = block[k];
+ if (!bigDone[c1])
+ ptr[ copyStart[c1]++ ] = k;
+ }
+ for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+ k = ptr[j]-1; if (k < 0) k += nblock;
+ c1 = block[k];
+ if (!bigDone[c1])
+ ptr[ copyEnd[c1]-- ] = k;
+ }
+ }
+
+ AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+ ||
+ /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+ Necessity for this case is demonstrated by compressing
+ a sequence of approximately 48.5 million of character
+ 251; 1.0.0/1.0.1 will then die here. */
+ (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+ 1007 )
+
+ for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+ /*--
+ Step 3:
+ The [ss] big bucket is now done. Record this fact,
+ and update the quadrant descriptors. Remember to
+ update quadrants in the overshoot area too, if
+ necessary. The "if (i < 255)" test merely skips
+ this updating for the last bucket processed, since
+ updating for the last bucket is pointless.
+
+ The quadrant array provides a way to incrementally
+ cache sort orderings, as they appear, so as to
+ make subsequent comparisons in fullGtU() complete
+ faster. For repetitive blocks this makes a big
+ difference (but not big enough to be able to avoid
+ the fallback sorting mechanism, exponential radix sort).
+
+ The precise meaning is: at all times:
+
+ for 0 <= i < nblock and 0 <= j <= nblock
+
+ if block[i] != block[j],
+
+ then the relative values of quadrant[i] and
+ quadrant[j] are meaningless.
+
+ else {
+ if quadrant[i] < quadrant[j]
+ then the string starting at i lexicographically
+ precedes the string starting at j
+
+ else if quadrant[i] > quadrant[j]
+ then the string starting at j lexicographically
+ precedes the string starting at i
+
+ else
+ the relative ordering of the strings starting
+ at i and j has not yet been determined.
+ }
+ --*/
+ bigDone[ss] = True;
+
+ if (i < 255) {
+ Int32 bbStart = ftab[ss << 8] & CLEARMASK;
+ Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+ Int32 shifts = 0;
+
+ while ((bbSize >> shifts) > 65534) shifts++;
+
+ for (j = bbSize-1; j >= 0; j--) {
+ Int32 a2update = ptr[bbStart + j];
+ UInt16 qVal = (UInt16)(j >> shifts);
+ quadrant[a2update] = qVal;
+ if (a2update < BZ_N_OVERSHOOT)
+ quadrant[a2update + nblock] = qVal;
+ }
+ AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+ }
+
+ }
+
+ if (verb >= 4)
+ VPrintf3 ( " %d pointers, %d sorted, %d scanned\n",
+ nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+ nblock > 0
+ arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+ ((UChar*)arr2) [0 .. nblock-1] holds block
+ arr1 exists for [0 .. nblock-1]
+
+ Post:
+ ((UChar*)arr2) [0 .. nblock-1] holds block
+ All other areas of block destroyed
+ ftab [ 0 .. 65536 ] destroyed
+ arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+ UInt32* ptr = s->ptr;
+ UChar* block = s->block;
+ UInt32* ftab = s->ftab;
+ Int32 nblock = s->nblock;
+ Int32 verb = s->verbosity;
+ Int32 wfact = s->workFactor;
+ UInt16* quadrant;
+ Int32 budget;
+ Int32 budgetInit;
+ Int32 i;
+
+ if (nblock < 10000) {
+ fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+ } else {
+ /* Calculate the location for quadrant, remembering to get
+ the alignment right. Assumes that &(block[0]) is at least
+ 2-byte aligned -- this should be ok since block is really
+ the first section of arr2.
+ */
+ i = nblock+BZ_N_OVERSHOOT;
+ if (i & 1) i++;
+ quadrant = (UInt16*)(&(block[i]));
+
+ /* (wfact-1) / 3 puts the default-factor-30
+ transition point at very roughly the same place as
+ with v0.1 and v0.9.0.
+ Not that it particularly matters any more, since the
+ resulting compressed stream is now the same regardless
+ of whether or not we use the main sort or fallback sort.
+ */
+ if (wfact < 1 ) wfact = 1;
+ if (wfact > 100) wfact = 100;
+ budgetInit = nblock * ((wfact-1) / 3);
+ budget = budgetInit;
+
+ mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+ if (verb >= 3)
+ VPrintf3 ( " %d work, %d block, ratio %5.2f\n",
+ budgetInit - budget,
+ nblock,
+ (float)(budgetInit - budget) /
+ (float)(nblock==0 ? 1 : nblock) );
+ if (budget < 0) {
+ if (verb >= 2)
+ VPrintf0 ( " too repetitive; using fallback"
+ " sorting algorithm\n" );
+ fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+ }
+ }
+
+ s->origPtr = -1;
+ for (i = 0; i < s->nblock; i++)
+ if (ptr[i] == 0)
+ { s->origPtr = i; break; };
+
+ AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end blocksort.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_compress.c b/lib/bzip2/bzlib_compress.c
new file mode 100644
index 00000000..68d948b4
--- /dev/null
+++ b/lib/bzip2/bzlib_compress.c
@@ -0,0 +1,713 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting) ---*/
+/*--- compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0.6 of 6 September 2010
+ Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+/* CHANGES
+ 0.9.0 -- original version.
+ 0.9.0a/b -- no changes in this file.
+ 0.9.0c -- changed setting of nGroups in sendMTFValues()
+ so as to do a bit better on small files
+*/
+
+#include "bzlib_private.h"
+#include <compiler.h>
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+ s->bsLive = 0;
+ s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+ while (s->bsLive > 0) {
+ s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+ s->numZ++;
+ s->bsBuff <<= 8;
+ s->bsLive -= 8;
+ }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz) \
+{ \
+ while (s->bsLive >= 8) { \
+ s->zbits[s->numZ] \
+ = (UChar)(s->bsBuff >> 24); \
+ s->numZ++; \
+ s->bsBuff <<= 8; \
+ s->bsLive -= 8; \
+ } \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+ bsNEEDW ( n );
+ s->bsBuff |= (v << (32 - s->bsLive - n));
+ s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+ bsW ( s, 8, (u >> 24) & 0xffL );
+ bsW ( s, 8, (u >> 16) & 0xffL );
+ bsW ( s, 8, (u >> 8) & 0xffL );
+ bsW ( s, 8, u & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+ bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+ Int32 i;
+ s->nInUse = 0;
+ for (i = 0; i < 256; i++)
+ if (s->inUse[i]) {
+ s->unseqToSeq[i] = s->nInUse;
+ s->nInUse++;
+ }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+ UChar yy[256];
+ Int32 i, j;
+ Int32 zPend;
+ Int32 wr;
+ Int32 EOB;
+
+ /*
+ After sorting (eg, here),
+ s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+ and
+ ((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
+ holds the original block data.
+
+ The first thing to do is generate the MTF values,
+ and put them in
+ ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+ Because there are strictly fewer or equal MTF values
+ than block values, ptr values in this area are overwritten
+ with MTF values only when they are no longer needed.
+
+ The final compressed bitstream is generated into the
+ area starting at
+ (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+ These storage aliases are set up in bzCompressInit(),
+ except for the last one, which is arranged in
+ compressBlock().
+ */
+ UInt32* ptr = s->ptr;
+ UChar* block = s->block;
+ UInt16* mtfv = s->mtfv;
+
+ makeMaps_e ( s );
+ EOB = s->nInUse+1;
+
+ for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+ wr = 0;
+ zPend = 0;
+ for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+ for (i = 0; i < s->nblock; i++) {
+ UChar ll_i;
+ AssertD ( wr <= i, "generateMTFValues(1)" );
+ j = ptr[i]-1; if (j < 0) j += s->nblock;
+ ll_i = s->unseqToSeq[block[j]];
+ AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+ if (yy[0] == ll_i) {
+ zPend++;
+ } else {
+
+ if (zPend > 0) {
+ zPend--;
+ while (True) {
+ if (zPend & 1) {
+ mtfv[wr] = BZ_RUNB; wr++;
+ s->mtfFreq[BZ_RUNB]++;
+ } else {
+ mtfv[wr] = BZ_RUNA; wr++;
+ s->mtfFreq[BZ_RUNA]++;
+ }
+ if (zPend < 2) break;
+ zPend = (zPend - 2) / 2;
+ };
+ zPend = 0;
+ }
+ {
+ register UChar rtmp;
+ register UChar* ryy_j;
+ register UChar rll_i;
+ rtmp = yy[1];
+ yy[1] = yy[0];
+ ryy_j = &(yy[1]);
+ rll_i = ll_i;
+ while ( rll_i != rtmp ) {
+ register UChar rtmp2;
+ ryy_j++;
+ rtmp2 = rtmp;
+ rtmp = *ryy_j;
+ *ryy_j = rtmp2;
+ };
+ yy[0] = rtmp;
+ j = ryy_j - &(yy[0]);
+ mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+ }
+
+ }
+ }
+
+ if (zPend > 0) {
+ zPend--;
+ while (True) {
+ if (zPend & 1) {
+ mtfv[wr] = BZ_RUNB; wr++;
+ s->mtfFreq[BZ_RUNB]++;
+ } else {
+ mtfv[wr] = BZ_RUNA; wr++;
+ s->mtfFreq[BZ_RUNA]++;
+ }
+ if (zPend < 2) break;
+ zPend = (zPend - 2) / 2;
+ };
+ zPend = 0;
+ }
+
+ mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+ s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST 0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+ Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+ Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+ Int32 nGroups;
+ Int32 nBytes __maybe_unused;
+
+ /*--
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ is a global since the decoder also needs it.
+
+ Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ are also globals only used in this proc.
+ Made global to keep stack frame size small.
+ --*/
+
+
+ UInt16 cost[BZ_N_GROUPS];
+ Int32 fave[BZ_N_GROUPS];
+
+ UInt16* mtfv = s->mtfv;
+
+ if (s->verbosity >= 3)
+ VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
+ "%d+2 syms in use\n",
+ s->nblock, s->nMTF, s->nInUse );
+
+ alphaSize = s->nInUse+2;
+ for (t = 0; t < BZ_N_GROUPS; t++)
+ for (v = 0; v < alphaSize; v++)
+ s->len[t][v] = BZ_GREATER_ICOST;
+
+ /*--- Decide how many coding tables to use ---*/
+ AssertH ( s->nMTF > 0, 3001 );
+ if (s->nMTF < 200) nGroups = 2; else
+ if (s->nMTF < 600) nGroups = 3; else
+ if (s->nMTF < 1200) nGroups = 4; else
+ if (s->nMTF < 2400) nGroups = 5; else
+ nGroups = 6;
+
+ /*--- Generate an initial set of coding tables ---*/
+ {
+ Int32 nPart, remF, tFreq, aFreq;
+
+ nPart = nGroups;
+ remF = s->nMTF;
+ gs = 0;
+ while (nPart > 0) {
+ tFreq = remF / nPart;
+ ge = gs-1;
+ aFreq = 0;
+ while (aFreq < tFreq && ge < alphaSize-1) {
+ ge++;
+ aFreq += s->mtfFreq[ge];
+ }
+
+ if (ge > gs
+ && nPart != nGroups && nPart != 1
+ && ((nGroups-nPart) % 2 == 1)) {
+ aFreq -= s->mtfFreq[ge];
+ ge--;
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf5( " initial group %d, [%d .. %d], "
+ "has %d syms (%4.1f%%)\n",
+ nPart, gs, ge, aFreq,
+ (100.0 * (float)aFreq) / (float)(s->nMTF) );
+
+ for (v = 0; v < alphaSize; v++)
+ if (v >= gs && v <= ge)
+ s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+ s->len[nPart-1][v] = BZ_GREATER_ICOST;
+
+ nPart--;
+ gs = ge+1;
+ remF -= aFreq;
+ }
+ }
+
+ /*---
+ Iterate up to BZ_N_ITERS times to improve the tables.
+ ---*/
+ for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+ for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+ for (t = 0; t < nGroups; t++)
+ for (v = 0; v < alphaSize; v++)
+ s->rfreq[t][v] = 0;
+
+ /*---
+ Set up an auxiliary length table which is used to fast-track
+ the common case (nGroups == 6).
+ ---*/
+ if (nGroups == 6) {
+ for (v = 0; v < alphaSize; v++) {
+ s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+ s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+ s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+ }
+ }
+
+ nSelectors = 0;
+ totc = 0;
+ gs = 0;
+ while (True) {
+
+ /*--- Set group start & end marks. --*/
+ if (gs >= s->nMTF) break;
+ ge = gs + BZ_G_SIZE - 1;
+ if (ge >= s->nMTF) ge = s->nMTF-1;
+
+ /*--
+ Calculate the cost of this group as coded
+ by each of the coding tables.
+ --*/
+ for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+ register UInt32 cost01, cost23, cost45;
+ register UInt16 icv;
+ cost01 = cost23 = cost45 = 0;
+
+# define BZ_ITER(nn) \
+ icv = mtfv[gs+(nn)]; \
+ cost01 += s->len_pack[icv][0]; \
+ cost23 += s->len_pack[icv][1]; \
+ cost45 += s->len_pack[icv][2]; \
+
+ BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
+ BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
+ BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+ BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+ BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+ BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+ BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+ BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+ BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+ BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+# undef BZ_ITER
+
+ cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+ cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+ cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++) {
+ UInt16 icv = mtfv[i];
+ for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+ }
+ }
+
+ /*--
+ Find the coding table which is best for this group,
+ and record its identity in the selector table.
+ --*/
+ bc = 999999999; bt = -1;
+ for (t = 0; t < nGroups; t++)
+ if (cost[t] < bc) { bc = cost[t]; bt = t; };
+ totc += bc;
+ fave[bt]++;
+ s->selector[nSelectors] = bt;
+ nSelectors++;
+
+ /*--
+ Increment the symbol frequencies for the selected table.
+ --*/
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+
+# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+ BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
+ BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
+ BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+ BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+ BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+ BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+ BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+ BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+ BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+ BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+# undef BZ_ITUR
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++)
+ s->rfreq[bt][ mtfv[i] ]++;
+ }
+
+ gs = ge+1;
+ }
+ if (s->verbosity >= 3) {
+ VPrintf2 ( " pass %d: size is %d, grp uses are ",
+ iter+1, totc/8 );
+ for (t = 0; t < nGroups; t++)
+ VPrintf1 ( "%d ", fave[t] );
+ VPrintf0 ( "\n" );
+ }
+
+ /*--
+ Recompute the tables based on the accumulated frequencies.
+ --*/
+ /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
+ comment in huffman.c for details. */
+ for (t = 0; t < nGroups; t++)
+ BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
+ alphaSize, 17 /*20*/ );
+ }
+
+
+ AssertH( nGroups < 8, 3002 );
+ AssertH( nSelectors < 32768 &&
+ nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+ 3003 );
+
+
+ /*--- Compute MTF values for the selectors. ---*/
+ {
+ UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+ for (i = 0; i < nGroups; i++) pos[i] = i;
+ for (i = 0; i < nSelectors; i++) {
+ ll_i = s->selector[i];
+ j = 0;
+ tmp = pos[j];
+ while ( ll_i != tmp ) {
+ j++;
+ tmp2 = tmp;
+ tmp = pos[j];
+ pos[j] = tmp2;
+ };
+ pos[0] = tmp;
+ s->selectorMtf[i] = j;
+ }
+ };
+
+ /*--- Assign actual codes for the tables. --*/
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+ if (s->len[t][i] < minLen) minLen = s->len[t][i];
+ }
+ AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+ AssertH ( !(minLen < 1), 3005 );
+ BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
+ minLen, maxLen, alphaSize );
+ }
+
+ /*--- Transmit the mapping table. ---*/
+ {
+ Bool inUse16[16];
+ for (i = 0; i < 16; i++) {
+ inUse16[i] = False;
+ for (j = 0; j < 16; j++)
+ if (s->inUse[i * 16 + j]) inUse16[i] = True;
+ }
+
+ nBytes = s->numZ;
+ for (i = 0; i < 16; i++)
+ if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+ for (i = 0; i < 16; i++)
+ if (inUse16[i])
+ for (j = 0; j < 16; j++) {
+ if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
+ }
+
+ /*--- Now the selectors. ---*/
+ nBytes = s->numZ;
+ bsW ( s, 3, nGroups );
+ bsW ( s, 15, nSelectors );
+ for (i = 0; i < nSelectors; i++) {
+ for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+ bsW(s,1,0);
+ }
+ if (s->verbosity >= 3)
+ VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+ /*--- Now the coding tables. ---*/
+ nBytes = s->numZ;
+
+ for (t = 0; t < nGroups; t++) {
+ Int32 curr = s->len[t][0];
+ bsW ( s, 5, curr );
+ for (i = 0; i < alphaSize; i++) {
+ while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+ while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+ bsW ( s, 1, 0 );
+ }
+ }
+
+ if (s->verbosity >= 3)
+ VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+ /*--- And finally, the block data proper ---*/
+ nBytes = s->numZ;
+ selCtr = 0;
+ gs = 0;
+ while (True) {
+ if (gs >= s->nMTF) break;
+ ge = gs + BZ_G_SIZE - 1;
+ if (ge >= s->nMTF) ge = s->nMTF-1;
+ AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+ if (nGroups == 6 && 50 == ge-gs+1) {
+ /*--- fast track the common case ---*/
+ UInt16 mtfv_i;
+ UChar* s_len_sel_selCtr
+ = &(s->len[s->selector[selCtr]][0]);
+ Int32* s_code_sel_selCtr
+ = &(s->code[s->selector[selCtr]][0]);
+
+# define BZ_ITAH(nn) \
+ mtfv_i = mtfv[gs+(nn)]; \
+ bsW ( s, \
+ s_len_sel_selCtr[mtfv_i], \
+ s_code_sel_selCtr[mtfv_i] )
+
+ BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
+ BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
+ BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+ BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+ BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+ BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+ BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+ BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+ BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+ BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+# undef BZ_ITAH
+
+ } else {
+ /*--- slow version which correctly handles all situations ---*/
+ for (i = gs; i <= ge; i++) {
+ bsW ( s,
+ s->len [s->selector[selCtr]] [mtfv[i]],
+ s->code [s->selector[selCtr]] [mtfv[i]] );
+ }
+ }
+
+
+ gs = ge+1;
+ selCtr++;
+ }
+ AssertH( selCtr == nSelectors, 3007 );
+
+ if (s->verbosity >= 3)
+ VPrintf1( "codes %d\n", s->numZ-nBytes );
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+ if (s->nblock > 0) {
+
+ BZ_FINALISE_CRC ( s->blockCRC );
+ s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+ s->combinedCRC ^= s->blockCRC;
+ if (s->blockNo > 1) s->numZ = 0;
+
+ if (s->verbosity >= 2)
+ VPrintf4( " block %d: crc = 0x%08x, "
+ "combined CRC = 0x%08x, size = %d\n",
+ s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+ BZ2_blockSort ( s );
+ }
+
+ s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+ /*-- If this is the first block, create the stream header. --*/
+ if (s->blockNo == 1) {
+ BZ2_bsInitWrite ( s );
+ bsPutUChar ( s, BZ_HDR_B );
+ bsPutUChar ( s, BZ_HDR_Z );
+ bsPutUChar ( s, BZ_HDR_h );
+ bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+ }
+
+ if (s->nblock > 0) {
+
+ bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+ bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+ bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+ /*-- Now the block's CRC, so it is in a known place. --*/
+ bsPutUInt32 ( s, s->blockCRC );
+
+ /*--
+ Now a single bit indicating (non-)randomisation.
+ As of version 0.9.5, we use a better sorting algorithm
+ which makes randomisation unnecessary. So always set
+ the randomised bit to 'no'. Of course, the decoder
+ still needs to be able to handle randomised blocks
+ so as to maintain backwards compatibility with
+ older versions of bzip2.
+ --*/
+ bsW(s,1,0);
+
+ bsW ( s, 24, s->origPtr );
+ generateMTFValues ( s );
+ sendMTFValues ( s );
+ }
+
+
+ /*-- If this is the last block, add the stream trailer. --*/
+ if (is_last_block) {
+
+ bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+ bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+ bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+ bsPutUInt32 ( s, s->combinedCRC );
+ if (s->verbosity >= 2)
+ VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
+ bsFinishWrite ( s );
+ }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end compress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_crctable.c b/lib/bzip2/bzlib_crctable.c
new file mode 100644
index 00000000..325b9664
--- /dev/null
+++ b/lib/bzip2/bzlib_crctable.c
@@ -0,0 +1,145 @@
+#include <config.h>
+
+/*-------------------------------------------------------------*/
+/*--- Table for doing CRCs ---*/
+/*--- crctable.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*--
+ I think this is an implementation of the AUTODIN-II,
+ Ethernet & FDDI 32-bit CRC standard. Vaguely derived
+ from code by Rob Warnock, in Section 51 of the
+ comp.compression FAQ.
+--*/
+
+UInt32 BZ2_crc32Table[256] = {
+
+ /*-- Ugly, innit? --*/
+
+ 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
+ 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
+ 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
+ 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
+ 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
+ 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
+ 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
+ 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
+ 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
+ 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
+ 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
+ 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
+ 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
+ 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
+ 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
+ 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
+ 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
+ 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
+ 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
+ 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
+ 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
+ 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
+ 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
+ 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
+ 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
+ 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
+ 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
+ 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
+ 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
+ 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
+ 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
+ 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
+ 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
+ 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
+ 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
+ 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
+ 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
+ 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
+ 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
+ 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
+ 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
+ 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
+ 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
+ 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
+ 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
+ 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
+ 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
+ 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
+ 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
+ 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
+ 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
+ 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
+ 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
+ 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
+ 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
+ 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
+ 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
+ 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
+ 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
+ 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
+ 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
+ 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
+ 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
+ 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end crctable.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_decompress.c b/lib/bzip2/bzlib_decompress.c
new file mode 100644
index 00000000..4412b8a2
--- /dev/null
+++ b/lib/bzip2/bzlib_decompress.c
@@ -0,0 +1,674 @@
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery ---*/
+/*--- decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+ Int32 i;
+ s->nInUse = 0;
+ for (i = 0; i < 256; i++)
+ if (s->inUse[i]) {
+ s->seqToUnseq[s->nInUse] = i;
+ s->nInUse++;
+ }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr) \
+ { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn) \
+ case lll: s->state = lll; \
+ while (True) { \
+ if (s->bsLive >= nnn) { \
+ UInt32 v; \
+ v = (s->bsBuff >> \
+ (s->bsLive-nnn)) & ((1 << nnn)-1); \
+ s->bsLive -= nnn; \
+ vvv = v; \
+ break; \
+ } \
+ if (s->strm->avail_in == 0) RETURN(BZ_OK); \
+ s->bsBuff \
+ = (s->bsBuff << 8) | \
+ ((UInt32) \
+ (*((UChar*)(s->strm->next_in)))); \
+ s->bsLive += 8; \
+ s->strm->next_in++; \
+ s->strm->avail_in--; \
+ s->strm->total_in_lo32++; \
+ if (s->strm->total_in_lo32 == 0) \
+ s->strm->total_in_hi32++; \
+ }
+
+#define GET_UCHAR(lll,uuu) \
+ GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu) \
+ GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval) \
+{ \
+ if (groupPos == 0) { \
+ groupNo++; \
+ if (groupNo >= nSelectors) \
+ RETURN(BZ_DATA_ERROR); \
+ groupPos = BZ_G_SIZE; \
+ gSel = s->selector[groupNo]; \
+ gMinlen = s->minLens[gSel]; \
+ gLimit = &(s->limit[gSel][0]); \
+ gPerm = &(s->perm[gSel][0]); \
+ gBase = &(s->base[gSel][0]); \
+ } \
+ groupPos--; \
+ zn = gMinlen; \
+ GET_BITS(label1, zvec, zn); \
+ while (1) { \
+ if (zn > 20 /* the longest code */) \
+ RETURN(BZ_DATA_ERROR); \
+ if (zvec <= gLimit[zn]) break; \
+ zn++; \
+ GET_BIT(label2, zj); \
+ zvec = (zvec << 1) | zj; \
+ }; \
+ if (zvec - gBase[zn] < 0 \
+ || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
+ RETURN(BZ_DATA_ERROR); \
+ lval = gPerm[zvec - gBase[zn]]; \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+ UChar uc;
+ Int32 retVal;
+ Int32 minLen, maxLen;
+ bz_stream* strm = s->strm;
+
+ /* stuff that needs to be saved/restored */
+ Int32 i;
+ Int32 j;
+ Int32 t;
+ Int32 alphaSize;
+ Int32 nGroups;
+ Int32 nSelectors;
+ Int32 EOB;
+ Int32 groupNo;
+ Int32 groupPos;
+ Int32 nextSym;
+ Int32 nblockMAX;
+ Int32 nblock;
+ Int32 es;
+ Int32 N;
+ Int32 curr;
+ Int32 zt;
+ Int32 zn;
+ Int32 zvec;
+ Int32 zj;
+ Int32 gSel;
+ Int32 gMinlen;
+ Int32* gLimit;
+ Int32* gBase;
+ Int32* gPerm;
+
+ if (s->state == BZ_X_MAGIC_1) {
+ /*initialise the save area*/
+ s->save_i = 0;
+ s->save_j = 0;
+ s->save_t = 0;
+ s->save_alphaSize = 0;
+ s->save_nGroups = 0;
+ s->save_nSelectors = 0;
+ s->save_EOB = 0;
+ s->save_groupNo = 0;
+ s->save_groupPos = 0;
+ s->save_nextSym = 0;
+ s->save_nblockMAX = 0;
+ s->save_nblock = 0;
+ s->save_es = 0;
+ s->save_N = 0;
+ s->save_curr = 0;
+ s->save_zt = 0;
+ s->save_zn = 0;
+ s->save_zvec = 0;
+ s->save_zj = 0;
+ s->save_gSel = 0;
+ s->save_gMinlen = 0;
+ s->save_gLimit = NULL;
+ s->save_gBase = NULL;
+ s->save_gPerm = NULL;
+ }
+
+ /*restore from the save area*/
+ i = s->save_i;
+ j = s->save_j;
+ t = s->save_t;
+ alphaSize = s->save_alphaSize;
+ nGroups = s->save_nGroups;
+ nSelectors = s->save_nSelectors;
+ EOB = s->save_EOB;
+ groupNo = s->save_groupNo;
+ groupPos = s->save_groupPos;
+ nextSym = s->save_nextSym;
+ nblockMAX = s->save_nblockMAX;
+ nblock = s->save_nblock;
+ es = s->save_es;
+ N = s->save_N;
+ curr = s->save_curr;
+ zt = s->save_zt;
+ zn = s->save_zn;
+ zvec = s->save_zvec;
+ zj = s->save_zj;
+ gSel = s->save_gSel;
+ gMinlen = s->save_gMinlen;
+ gLimit = s->save_gLimit;
+ gBase = s->save_gBase;
+ gPerm = s->save_gPerm;
+
+ retVal = BZ_OK;
+
+ switch (s->state) {
+
+ GET_UCHAR(BZ_X_MAGIC_1, uc);
+ if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_2, uc);
+ if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_3, uc)
+ if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+ if (s->blockSize100k < (BZ_HDR_0 + 1) ||
+ s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
+ s->blockSize100k -= BZ_HDR_0;
+
+ if (s->smallDecompress) {
+ s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+ s->ll4 = BZALLOC(
+ ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
+ );
+ if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+ } else {
+ s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+ if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+ }
+
+ GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+ if (uc == 0x17) goto endhdr_2;
+ if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_2, uc);
+ if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_3, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_4, uc);
+ if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_5, uc);
+ if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_6, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+ s->currBlockNo++;
+ if (s->verbosity >= 2)
+ VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
+
+ s->storedBlockCRC = 0;
+ GET_UCHAR(BZ_X_BCRC_1, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_2, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_3, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_4, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+ GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+ s->origPtr = 0;
+ GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+ if (s->origPtr < 0)
+ RETURN(BZ_DATA_ERROR);
+ if (s->origPtr > 10 + 100000*s->blockSize100k)
+ RETURN(BZ_DATA_ERROR);
+
+ /*--- Receive the mapping table ---*/
+ for (i = 0; i < 16; i++) {
+ GET_BIT(BZ_X_MAPPING_1, uc);
+ if (uc == 1)
+ s->inUse16[i] = True; else
+ s->inUse16[i] = False;
+ }
+
+ for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+ for (i = 0; i < 16; i++)
+ if (s->inUse16[i])
+ for (j = 0; j < 16; j++) {
+ GET_BIT(BZ_X_MAPPING_2, uc);
+ if (uc == 1) s->inUse[i * 16 + j] = True;
+ }
+ makeMaps_d ( s );
+ if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+ alphaSize = s->nInUse+2;
+
+ /*--- Now the selectors ---*/
+ GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+ if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+ GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+ if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+ for (i = 0; i < nSelectors; i++) {
+ j = 0;
+ while (True) {
+ GET_BIT(BZ_X_SELECTOR_3, uc);
+ if (uc == 0) break;
+ j++;
+ if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+ }
+ s->selectorMtf[i] = j;
+ }
+
+ /*--- Undo the MTF values for the selectors. ---*/
+ {
+ UChar pos[BZ_N_GROUPS], tmp, v;
+ for (v = 0; v < nGroups; v++) pos[v] = v;
+
+ for (i = 0; i < nSelectors; i++) {
+ v = s->selectorMtf[i];
+ tmp = pos[v];
+ while (v > 0) { pos[v] = pos[v-1]; v--; }
+ pos[0] = tmp;
+ s->selector[i] = tmp;
+ }
+ }
+
+ /*--- Now the coding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ GET_BITS(BZ_X_CODING_1, curr, 5);
+ for (i = 0; i < alphaSize; i++) {
+ while (True) {
+ if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+ GET_BIT(BZ_X_CODING_2, uc);
+ if (uc == 0) break;
+ GET_BIT(BZ_X_CODING_3, uc);
+ if (uc == 0) curr++; else curr--;
+ }
+ s->len[t][i] = curr;
+ }
+ }
+
+ /*--- Create the Huffman decoding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+ if (s->len[t][i] < minLen) minLen = s->len[t][i];
+ }
+ BZ2_hbCreateDecodeTables (
+ &(s->limit[t][0]),
+ &(s->base[t][0]),
+ &(s->perm[t][0]),
+ &(s->len[t][0]),
+ minLen, maxLen, alphaSize
+ );
+ s->minLens[t] = minLen;
+ }
+
+ /*--- Now the MTF values ---*/
+
+ EOB = s->nInUse+1;
+ nblockMAX = 100000 * s->blockSize100k;
+ groupNo = -1;
+ groupPos = 0;
+
+ for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+ /*-- MTF init --*/
+ {
+ Int32 ii, jj, kk;
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ /*-- end MTF init --*/
+
+ nblock = 0;
+ GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+ while (True) {
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ if (nextSym == EOB) break;
+
+ if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+ es = -1;
+ N = 1;
+ do {
+ if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+ if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+ N = N * 2;
+ GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+ }
+ while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+ es++;
+ uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+ s->unzftab[uc] += es;
+
+ if (s->smallDecompress)
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->ll16[nblock] = (UInt16)uc;
+ nblock++;
+ es--;
+ }
+ else
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->tt[nblock] = (UInt32)uc;
+ nblock++;
+ es--;
+ };
+
+ continue;
+
+ } else {
+
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+ /*-- uc = MTF ( nextSym-1 ) --*/
+ {
+ Int32 ii, jj, kk, pp, lno, off;
+ UInt32 nn;
+ nn = (UInt32)(nextSym - 1);
+
+ if (nn < MTFL_SIZE) {
+ /* avoid general-case expense */
+ pp = s->mtfbase[0];
+ uc = s->mtfa[pp+nn];
+ while (nn > 3) {
+ Int32 z = pp+nn;
+ s->mtfa[(z) ] = s->mtfa[(z)-1];
+ s->mtfa[(z)-1] = s->mtfa[(z)-2];
+ s->mtfa[(z)-2] = s->mtfa[(z)-3];
+ s->mtfa[(z)-3] = s->mtfa[(z)-4];
+ nn -= 4;
+ }
+ while (nn > 0) {
+ s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
+ };
+ s->mtfa[pp] = uc;
+ } else {
+ /* general case */
+ lno = nn / MTFL_SIZE;
+ off = nn % MTFL_SIZE;
+ pp = s->mtfbase[lno] + off;
+ uc = s->mtfa[pp];
+ while (pp > s->mtfbase[lno]) {
+ s->mtfa[pp] = s->mtfa[pp-1]; pp--;
+ };
+ s->mtfbase[lno]++;
+ while (lno > 0) {
+ s->mtfbase[lno]--;
+ s->mtfa[s->mtfbase[lno]]
+ = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+ lno--;
+ }
+ s->mtfbase[0]--;
+ s->mtfa[s->mtfbase[0]] = uc;
+ if (s->mtfbase[0] == 0) {
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ }
+ }
+ /*-- end uc = MTF ( nextSym-1 ) --*/
+
+ s->unzftab[s->seqToUnseq[uc]]++;
+ if (s->smallDecompress)
+ s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+ s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
+ nblock++;
+
+ GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+ continue;
+ }
+ }
+
+ /* Now we know what nblock is, we can do a better sanity
+ check on s->origPtr.
+ */
+ if (s->origPtr < 0 || s->origPtr >= nblock)
+ RETURN(BZ_DATA_ERROR);
+
+ s->state_out_len = 0;
+ s->state_out_ch = 0;
+ BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+ s->state = BZ_X_OUTPUT;
+ if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+ /*-- Set up cftab to facilitate generation of T^(-1) --*/
+ s->cftab[0] = 0;
+ for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+ for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+
+ if (s->smallDecompress) {
+
+ /*-- Make a copy of cftab, used in generation of T --*/
+ for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+ /*-- compute the T vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->ll16[i]);
+ SET_LL(i, s->cftabCopy[uc]);
+ s->cftabCopy[uc]++;
+ }
+
+ /*-- Compute T^(-1) by pointer reversal on T --*/
+ i = s->origPtr;
+ j = GET_LL(i);
+ do {
+ Int32 tmp = GET_LL(j);
+ SET_LL(j, i);
+ i = j;
+ j = tmp;
+ }
+ while (i != s->origPtr);
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ s->tPos = s->origPtr;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ }
+
+ } else {
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ /*-- compute the T^(-1) vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->tt[i] & 0xff);
+ s->tt[s->cftab[uc]] |= (i << 8);
+ s->cftab[uc]++;
+ }
+
+ s->tPos = s->tt[s->origPtr] >> 8;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ }
+
+ }
+
+ RETURN(BZ_OK);
+
+
+ endhdr_2:
+
+ GET_UCHAR(BZ_X_ENDHDR_2, uc);
+ if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_3, uc);
+ if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_4, uc);
+ if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_5, uc);
+ if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_6, uc);
+ if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+ s->storedCombinedCRC = 0;
+ GET_UCHAR(BZ_X_CCRC_1, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_2, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_3, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_4, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+ s->state = BZ_X_IDLE;
+ RETURN(BZ_STREAM_END);
+
+ default: AssertH ( False, 4001 );
+ }
+
+ AssertH ( False, 4002 );
+
+ save_state_and_return:
+
+ s->save_i = i;
+ s->save_j = j;
+ s->save_t = t;
+ s->save_alphaSize = alphaSize;
+ s->save_nGroups = nGroups;
+ s->save_nSelectors = nSelectors;
+ s->save_EOB = EOB;
+ s->save_groupNo = groupNo;
+ s->save_groupPos = groupPos;
+ s->save_nextSym = nextSym;
+ s->save_nblockMAX = nblockMAX;
+ s->save_nblock = nblock;
+ s->save_es = es;
+ s->save_N = N;
+ s->save_curr = curr;
+ s->save_zt = zt;
+ s->save_zn = zn;
+ s->save_zvec = zvec;
+ s->save_zj = zj;
+ s->save_gSel = gSel;
+ s->save_gMinlen = gMinlen;
+ s->save_gLimit = gLimit;
+ s->save_gBase = gBase;
+ s->save_gPerm = gPerm;
+
+ return retVal;
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end decompress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_huffman.c b/lib/bzip2/bzlib_huffman.c
new file mode 100644
index 00000000..801b8ec3
--- /dev/null
+++ b/lib/bzip2/bzlib_huffman.c
@@ -0,0 +1,229 @@
+#include <config.h>
+
+/*-------------------------------------------------------------*/
+/*--- Huffman coding low-level stuff ---*/
+/*--- huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+/*---------------------------------------------------*/
+#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
+#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
+#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
+
+#define ADDWEIGHTS(zw1,zw2) \
+ (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
+ (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
+
+#define UPHEAP(z) \
+{ \
+ Int32 zz, tmp; \
+ zz = z; tmp = heap[zz]; \
+ while (weight[tmp] < weight[heap[zz >> 1]]) { \
+ heap[zz] = heap[zz >> 1]; \
+ zz >>= 1; \
+ } \
+ heap[zz] = tmp; \
+}
+
+#define DOWNHEAP(z) \
+{ \
+ Int32 zz, yy, tmp; \
+ zz = z; tmp = heap[zz]; \
+ while (True) { \
+ yy = zz << 1; \
+ if (yy > nHeap) break; \
+ if (yy < nHeap && \
+ weight[heap[yy+1]] < weight[heap[yy]]) \
+ yy++; \
+ if (weight[tmp] < weight[heap[yy]]) break; \
+ heap[zz] = heap[yy]; \
+ zz = yy; \
+ } \
+ heap[zz] = tmp; \
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbMakeCodeLengths ( UChar *len,
+ Int32 *freq,
+ Int32 alphaSize,
+ Int32 maxLen )
+{
+ /*--
+ Nodes and heap entries run from 1. Entry 0
+ for both the heap and nodes is a sentinel.
+ --*/
+ Int32 nNodes, nHeap, n1, n2, i, j, k;
+ Bool tooLong;
+
+ Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
+ Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
+ Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
+
+ for (i = 0; i < alphaSize; i++)
+ weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+
+ while (True) {
+
+ nNodes = alphaSize;
+ nHeap = 0;
+
+ heap[0] = 0;
+ weight[0] = 0;
+ parent[0] = -2;
+
+ for (i = 1; i <= alphaSize; i++) {
+ parent[i] = -1;
+ nHeap++;
+ heap[nHeap] = i;
+ UPHEAP(nHeap);
+ }
+
+ AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
+
+ while (nHeap > 1) {
+ n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+ n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+ nNodes++;
+ parent[n1] = parent[n2] = nNodes;
+ weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
+ parent[nNodes] = -1;
+ nHeap++;
+ heap[nHeap] = nNodes;
+ UPHEAP(nHeap);
+ }
+
+ AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
+
+ tooLong = False;
+ for (i = 1; i <= alphaSize; i++) {
+ j = 0;
+ k = i;
+ while (parent[k] >= 0) { k = parent[k]; j++; }
+ len[i-1] = j;
+ if (j > maxLen) tooLong = True;
+ }
+
+ if (! tooLong) break;
+
+ for (i = 1; i < alphaSize; i++) {
+ j = weight[i] >> 8;
+ j = 1 + (j / 2);
+ weight[i] = j << 8;
+ }
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbAssignCodes ( Int32 *code,
+ UChar *length,
+ Int32 minLen,
+ Int32 maxLen,
+ Int32 alphaSize )
+{
+ Int32 n, vec, i;
+
+ vec = 0;
+ for (n = minLen; n <= maxLen; n++) {
+ for (i = 0; i < alphaSize; i++)
+ if (length[i] == n) { code[i] = vec; vec++; };
+ vec <<= 1;
+ }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbCreateDecodeTables ( Int32 *limit,
+ Int32 *base,
+ Int32 *perm,
+ UChar *length,
+ Int32 minLen,
+ Int32 maxLen,
+ Int32 alphaSize )
+{
+ Int32 pp, i, j, vec;
+
+ pp = 0;
+ for (i = minLen; i <= maxLen; i++)
+ for (j = 0; j < alphaSize; j++)
+ if (length[j] == i) { perm[pp] = j; pp++; };
+
+ for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
+ for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
+
+ for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
+
+ for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
+ vec = 0;
+
+ for (i = minLen; i <= maxLen; i++) {
+ vec += (base[i+1] - base[i]);
+ limit[i] = vec-1;
+ vec <<= 1;
+ }
+ for (i = minLen + 1; i <= maxLen; i++)
+ base[i] = ((limit[i-1] + 1) << 1) - base[i];
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end huffman.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_private.h b/lib/bzip2/bzlib_private.h
new file mode 100644
index 00000000..87d8f945
--- /dev/null
+++ b/lib/bzip2/bzlib_private.h
@@ -0,0 +1,530 @@
+/*
+ * This file is a modified version of bzlib_private.h from the bzip2-1.0.2
+ * distribution which can be found at http://sources.redhat.com/bzip2/
+ */
+
+/*-------------------------------------------------------------*/
+/*--- Private header file for the library. ---*/
+/*--- bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+#ifndef _BZLIB_PRIVATE_H
+#define _BZLIB_PRIVATE_H
+
+#include <malloc.h>
+
+#include "bzlib.h"
+
+#ifndef BZ_NO_STDIO
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#endif
+
+
+/*-- General stuff. --*/
+
+#define BZ_VERSION "1.0.2, 30-Dec-2001"
+
+typedef char Char;
+typedef unsigned char Bool;
+typedef unsigned char UChar;
+typedef int Int32;
+typedef unsigned int UInt32;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#define True ((Bool)1)
+#define False ((Bool)0)
+
+#ifndef __GNUC__
+#define __inline__ /* */
+#endif
+
+#ifndef BZ_NO_STDIO
+extern void BZ2_bz__AssertH__fail ( int errcode );
+#define AssertH(cond,errcode) \
+ { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
+#if BZ_DEBUG
+#define AssertD(cond,msg) \
+ { if (!(cond)) { \
+ fprintf ( stderr, \
+ "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
+ exit(1); \
+ }}
+#else
+#define AssertD(cond,msg) /* */
+#endif
+#define VPrintf0(zf) \
+ fprintf(stderr,zf)
+#define VPrintf1(zf,za1) \
+ fprintf(stderr,zf,za1)
+#define VPrintf2(zf,za1,za2) \
+ fprintf(stderr,zf,za1,za2)
+#define VPrintf3(zf,za1,za2,za3) \
+ fprintf(stderr,zf,za1,za2,za3)
+#define VPrintf4(zf,za1,za2,za3,za4) \
+ fprintf(stderr,zf,za1,za2,za3,za4)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) \
+ fprintf(stderr,zf,za1,za2,za3,za4,za5)
+#else
+extern void bz_internal_error ( int errcode );
+#define AssertH(cond,errcode) \
+ { if (!(cond)) bz_internal_error ( errcode ); }
+#define AssertD(cond,msg) /* */
+#define VPrintf0(zf) /* */
+#define VPrintf1(zf,za1) /* */
+#define VPrintf2(zf,za1,za2) /* */
+#define VPrintf3(zf,za1,za2,za3) /* */
+#define VPrintf4(zf,za1,za2,za3,za4) /* */
+#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */
+#endif
+
+
+#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
+#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
+
+
+/*-- Header bytes. --*/
+
+#define BZ_HDR_B 0x42 /* 'B' */
+#define BZ_HDR_Z 0x5a /* 'Z' */
+#define BZ_HDR_h 0x68 /* 'h' */
+#define BZ_HDR_0 0x30 /* '0' */
+
+/*-- Constants for the back end. --*/
+
+#define BZ_MAX_ALPHA_SIZE 258
+#define BZ_MAX_CODE_LEN 23
+
+#define BZ_RUNA 0
+#define BZ_RUNB 1
+
+#define BZ_N_GROUPS 6
+#define BZ_G_SIZE 50
+#define BZ_N_ITERS 4
+
+#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
+
+
+/*-- Stuff for randomising repetitive blocks. --*/
+
+extern Int32 BZ2_rNums[512];
+
+#define BZ_RAND_DECLS \
+ Int32 rNToGo; \
+ Int32 rTPos \
+
+#define BZ_RAND_INIT_MASK \
+ s->rNToGo = 0; \
+ s->rTPos = 0 \
+
+#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
+
+#define BZ_RAND_UPD_MASK \
+ if (s->rNToGo == 0) { \
+ s->rNToGo = BZ2_rNums[s->rTPos]; \
+ s->rTPos++; \
+ if (s->rTPos == 512) s->rTPos = 0; \
+ } \
+ s->rNToGo--;
+
+
+/*-- Stuff for doing CRCs. --*/
+
+extern UInt32 BZ2_crc32Table[256];
+
+#define BZ_INITIALISE_CRC(crcVar) \
+{ \
+ crcVar = 0xffffffffL; \
+}
+
+#define BZ_FINALISE_CRC(crcVar) \
+{ \
+ crcVar = ~(crcVar); \
+}
+
+#define BZ_UPDATE_CRC(crcVar,cha) \
+{ \
+ crcVar = (crcVar << 8) ^ \
+ BZ2_crc32Table[(crcVar >> 24) ^ \
+ ((UChar)cha)]; \
+}
+
+
+/*-- States and modes for compression. --*/
+
+#define BZ_M_IDLE 1
+#define BZ_M_RUNNING 2
+#define BZ_M_FLUSHING 3
+#define BZ_M_FINISHING 4
+
+#define BZ_S_OUTPUT 1
+#define BZ_S_INPUT 2
+
+#define BZ_N_RADIX 2
+#define BZ_N_QSORT 12
+#define BZ_N_SHELL 18
+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
+
+
+/*-- Structure holding all the compression-side stuff. --*/
+
+typedef
+ struct {
+ /* pointer back to the struct bz_stream */
+ bz_stream* strm;
+
+ /* mode this stream is in, and whether inputting */
+ /* or outputting data */
+ Int32 mode;
+ Int32 state;
+
+ /* remembers avail_in when flush/finish requested */
+ UInt32 avail_in_expect;
+
+ /* for doing the block sorting */
+ UInt32* arr1;
+ UInt32* arr2;
+ UInt32* ftab;
+ Int32 origPtr;
+
+ /* aliases for arr1 and arr2 */
+ UInt32* ptr;
+ UChar* block;
+ UInt16* mtfv;
+ UChar* zbits;
+
+ /* for deciding when to use the fallback sorting algorithm */
+ Int32 workFactor;
+
+ /* run-length-encoding of the input */
+ UInt32 state_in_ch;
+ Int32 state_in_len;
+ BZ_RAND_DECLS;
+
+ /* input and output limits and current posns */
+ Int32 nblock;
+ Int32 nblockMAX;
+ Int32 numZ;
+ Int32 state_out_pos;
+
+ /* map of bytes used in block */
+ Int32 nInUse;
+ Bool inUse[256];
+ UChar unseqToSeq[256];
+
+ /* the buffer for bit stream creation */
+ UInt32 bsBuff;
+ Int32 bsLive;
+
+ /* block and combined CRCs */
+ UInt32 blockCRC;
+ UInt32 combinedCRC;
+
+ /* misc administratium */
+ Int32 verbosity;
+ Int32 blockNo;
+ Int32 blockSize100k;
+
+ /* stuff for coding the MTF values */
+ Int32 nMTF;
+ Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
+ UChar selector [BZ_MAX_SELECTORS];
+ UChar selectorMtf[BZ_MAX_SELECTORS];
+
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ /* second dimension: only 3 needed; 4 makes index calculations faster */
+ UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
+
+ }
+ EState;
+
+
+/*-- externs for compression. --*/
+
+extern void
+BZ2_blockSort ( EState* );
+
+extern void
+BZ2_compressBlock ( EState*, Bool );
+
+extern void
+BZ2_bsInitWrite ( EState* );
+
+extern void
+BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
+
+extern void
+BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
+
+
+/*-- states for decompression. --*/
+
+#define BZ_X_IDLE 1
+#define BZ_X_OUTPUT 2
+
+#define BZ_X_MAGIC_1 10
+#define BZ_X_MAGIC_2 11
+#define BZ_X_MAGIC_3 12
+#define BZ_X_MAGIC_4 13
+#define BZ_X_BLKHDR_1 14
+#define BZ_X_BLKHDR_2 15
+#define BZ_X_BLKHDR_3 16
+#define BZ_X_BLKHDR_4 17
+#define BZ_X_BLKHDR_5 18
+#define BZ_X_BLKHDR_6 19
+#define BZ_X_BCRC_1 20
+#define BZ_X_BCRC_2 21
+#define BZ_X_BCRC_3 22
+#define BZ_X_BCRC_4 23
+#define BZ_X_RANDBIT 24
+#define BZ_X_ORIGPTR_1 25
+#define BZ_X_ORIGPTR_2 26
+#define BZ_X_ORIGPTR_3 27
+#define BZ_X_MAPPING_1 28
+#define BZ_X_MAPPING_2 29
+#define BZ_X_SELECTOR_1 30
+#define BZ_X_SELECTOR_2 31
+#define BZ_X_SELECTOR_3 32
+#define BZ_X_CODING_1 33
+#define BZ_X_CODING_2 34
+#define BZ_X_CODING_3 35
+#define BZ_X_MTF_1 36
+#define BZ_X_MTF_2 37
+#define BZ_X_MTF_3 38
+#define BZ_X_MTF_4 39
+#define BZ_X_MTF_5 40
+#define BZ_X_MTF_6 41
+#define BZ_X_ENDHDR_2 42
+#define BZ_X_ENDHDR_3 43
+#define BZ_X_ENDHDR_4 44
+#define BZ_X_ENDHDR_5 45
+#define BZ_X_ENDHDR_6 46
+#define BZ_X_CCRC_1 47
+#define BZ_X_CCRC_2 48
+#define BZ_X_CCRC_3 49
+#define BZ_X_CCRC_4 50
+
+
+/*-- Constants for the fast MTF decoder. --*/
+
+#define MTFA_SIZE 4096
+#define MTFL_SIZE 16
+
+
+/*-- Structure holding all the decompression-side stuff. --*/
+
+typedef
+ struct {
+ /* pointer back to the struct bz_stream */
+ bz_stream* strm;
+
+ /* state indicator for this stream */
+ Int32 state;
+
+ /* for doing the final run-length decoding */
+ UChar state_out_ch;
+ Int32 state_out_len;
+ Bool blockRandomised;
+ BZ_RAND_DECLS;
+
+ /* the buffer for bit stream reading */
+ UInt32 bsBuff;
+ Int32 bsLive;
+
+ /* misc administratium */
+ Int32 blockSize100k;
+ Bool smallDecompress;
+ Int32 currBlockNo;
+ Int32 verbosity;
+
+ /* for undoing the Burrows-Wheeler transform */
+ Int32 origPtr;
+ UInt32 tPos;
+ Int32 k0;
+ Int32 unzftab[256];
+ Int32 nblock_used;
+ Int32 cftab[257];
+ Int32 cftabCopy[257];
+
+ /* for undoing the Burrows-Wheeler transform (FAST) */
+ UInt32 *tt;
+
+ /* for undoing the Burrows-Wheeler transform (SMALL) */
+ UInt16 *ll16;
+ UChar *ll4;
+
+ /* stored and calculated CRCs */
+ UInt32 storedBlockCRC;
+ UInt32 storedCombinedCRC;
+ UInt32 calculatedBlockCRC;
+ UInt32 calculatedCombinedCRC;
+
+ /* map of bytes used in block */
+ Int32 nInUse;
+ Bool inUse[256];
+ Bool inUse16[16];
+ UChar seqToUnseq[256];
+
+ /* for decoding the MTF values */
+ UChar mtfa [MTFA_SIZE];
+ Int32 mtfbase[256 / MTFL_SIZE];
+ UChar selector [BZ_MAX_SELECTORS];
+ UChar selectorMtf[BZ_MAX_SELECTORS];
+ UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+
+ Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+ Int32 minLens[BZ_N_GROUPS];
+
+ /* save area for scalars in the main decompress code */
+ Int32 save_i;
+ Int32 save_j;
+ Int32 save_t;
+ Int32 save_alphaSize;
+ Int32 save_nGroups;
+ Int32 save_nSelectors;
+ Int32 save_EOB;
+ Int32 save_groupNo;
+ Int32 save_groupPos;
+ Int32 save_nextSym;
+ Int32 save_nblockMAX;
+ Int32 save_nblock;
+ Int32 save_es;
+ Int32 save_N;
+ Int32 save_curr;
+ Int32 save_zt;
+ Int32 save_zn;
+ Int32 save_zvec;
+ Int32 save_zj;
+ Int32 save_gSel;
+ Int32 save_gMinlen;
+ Int32* save_gLimit;
+ Int32* save_gBase;
+ Int32* save_gPerm;
+
+ }
+ DState;
+
+
+/*-- Macros for decompression. --*/
+
+#define BZ_GET_FAST(cccc) \
+ s->tPos = s->tt[s->tPos]; \
+ cccc = (UChar)(s->tPos & 0xff); \
+ s->tPos >>= 8;
+
+#define BZ_GET_FAST_C(cccc) \
+ c_tPos = c_tt[c_tPos]; \
+ cccc = (UChar)(c_tPos & 0xff); \
+ c_tPos >>= 8;
+
+#define SET_LL4(i,n) \
+ { if (((i) & 0x1) == 0) \
+ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
+ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
+ }
+
+#define GET_LL4(i) \
+ ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
+
+#define SET_LL(i,n) \
+ { s->ll16[i] = (UInt16)(n & 0x0000ffff); \
+ SET_LL4(i, n >> 16); \
+ }
+
+#define GET_LL(i) \
+ (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
+
+#define BZ_GET_SMALL(cccc) \
+ cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
+ s->tPos = GET_LL(s->tPos);
+
+
+/*-- externs for decompression. --*/
+
+extern Int32
+BZ2_indexIntoF ( Int32, Int32* );
+
+extern Int32
+BZ2_decompress ( DState* );
+
+extern void
+BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
+ Int32, Int32, Int32 );
+
+
+#endif
+
+
+/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
+
+#ifdef BZ_NO_STDIO
+#ifndef NULL
+#define NULL 0
+#endif
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/bzip2/bzlib_randtable.c b/lib/bzip2/bzlib_randtable.c
new file mode 100644
index 00000000..c3dc7e41
--- /dev/null
+++ b/lib/bzip2/bzlib_randtable.c
@@ -0,0 +1,125 @@
+#include <config.h>
+
+/*-------------------------------------------------------------*/
+/*--- Table for randomising repetitive blocks ---*/
+/*--- randtable.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2002 Julian R Seward. 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. 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.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ Julian Seward, Cambridge, UK.
+ jseward@acm.org
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+#include "bzlib_private.h"
+
+
+/*---------------------------------------------*/
+Int32 BZ2_rNums[512] = {
+ 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+ 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+ 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+ 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+ 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+ 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+ 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+ 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+ 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+ 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+ 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+ 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+ 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+ 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+ 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+ 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+ 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+ 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+ 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+ 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+ 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+ 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+ 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+ 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+ 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+ 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+ 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+ 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+ 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+ 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+ 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+ 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+ 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+ 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+ 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+ 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+ 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+ 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+ 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+ 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+ 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+ 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+ 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+ 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+ 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+ 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+ 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+ 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+ 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+ 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+ 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+ 936, 638
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end randtable.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/lib/charset.c b/lib/charset.c
new file mode 100644
index 00000000..1c6a7f69
--- /dev/null
+++ b/lib/charset.c
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * charset conversion utils
+ *
+ * Copyright (c) 2017 Rob Clark
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <capitalization.h>
+#include <malloc.h>
+
+static struct capitalization_table capitalization_table[] =
+#ifdef CONFIG_EFI_UNICODE_CAPITALIZATION
+ UNICODE_CAPITALIZATION_TABLE;
+#elif CONFIG_FAT_DEFAULT_CODEPAGE == 1250
+ CP1250_CAPITALIZATION_TABLE;
+#else
+ CP437_CAPITALIZATION_TABLE;
+#endif
+
+/**
+ * get_code() - read Unicode code point from UTF-8 stream
+ *
+ * @read_u8: - stream reader
+ * @src: - string buffer passed to stream reader, optional
+ * Return: - Unicode code point
+ */
+static int get_code(u8 (*read_u8)(void *data), void *data)
+{
+ s32 ch = 0;
+
+ ch = read_u8(data);
+ if (!ch)
+ return 0;
+ if (ch >= 0xc2 && ch <= 0xf4) {
+ int code = 0;
+
+ if (ch >= 0xe0) {
+ if (ch >= 0xf0) {
+ /* 0xf0 - 0xf4 */
+ ch &= 0x07;
+ code = ch << 18;
+ ch = read_u8(data);
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ ch &= 0x3f;
+ } else {
+ /* 0xe0 - 0xef */
+ ch &= 0x0f;
+ }
+ code += ch << 12;
+ if ((code >= 0xD800 && code <= 0xDFFF) ||
+ code >= 0x110000)
+ goto error;
+ ch = read_u8(data);
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ }
+ /* 0xc0 - 0xdf or continuation byte (0x80 - 0xbf) */
+ ch &= 0x3f;
+ code += ch << 6;
+ ch = read_u8(data);
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ ch &= 0x3f;
+ ch += code;
+ } else if (ch >= 0x80) {
+ goto error;
+ }
+ return ch;
+error:
+ return '?';
+}
+
+/**
+ * read_string() - read byte from character string
+ *
+ * @data: - pointer to string
+ * Return: - byte read
+ *
+ * The string pointer is incremented if it does not point to '\0'.
+ */
+static u8 read_string(void *data)
+
+{
+ const char **src = (const char **)data;
+ u8 c;
+
+ if (!src || !*src || !**src)
+ return 0;
+ c = **src;
+ ++*src;
+ return c;
+}
+
+/**
+ * read_console() - read byte from console
+ *
+ * @data - not used, needed to match interface
+ * Return: - byte read or 0 on error
+ */
+static u8 read_console(void *data)
+{
+ int ch;
+
+ ch = getc();
+ if (ch < 0)
+ ch = 0;
+ return ch;
+}
+
+int console_read_unicode(s32 *code)
+{
+ if (!tstc()) {
+ /* No input available */
+ return 1;
+ }
+
+ /* Read Unicode code */
+ *code = get_code(read_console, NULL);
+ return 0;
+}
+
+s32 utf8_get(const char **src)
+{
+ return get_code(read_string, src);
+}
+
+int utf8_put(s32 code, char **dst)
+{
+ if (!dst || !*dst)
+ return -1;
+ if ((code >= 0xD800 && code <= 0xDFFF) || code >= 0x110000)
+ return -1;
+ if (code <= 0x007F) {
+ **dst = code;
+ } else {
+ if (code <= 0x07FF) {
+ **dst = code >> 6 | 0xC0;
+ } else {
+ if (code < 0x10000) {
+ **dst = code >> 12 | 0xE0;
+ } else {
+ **dst = code >> 18 | 0xF0;
+ ++*dst;
+ **dst = (code >> 12 & 0x3F) | 0x80;
+ }
+ ++*dst;
+ **dst = (code >> 6 & 0x3F) | 0x80;
+ }
+ ++*dst;
+ **dst = (code & 0x3F) | 0x80;
+ }
+ ++*dst;
+ return 0;
+}
+
+size_t utf8_utf16_strnlen(const char *src, size_t count)
+{
+ size_t len = 0;
+
+ for (; *src && count; --count) {
+ s32 code = utf8_get(&src);
+
+ if (!code)
+ break;
+ if (code < 0) {
+ /* Reserve space for a replacement character */
+ len += 1;
+ } else if (code < 0x10000) {
+ len += 1;
+ } else {
+ len += 2;
+ }
+ }
+ return len;
+}
+
+int utf8_utf16_strncpy(u16 **dst, const char *src, size_t count)
+{
+ if (!src || !dst || !*dst)
+ return -1;
+
+ for (; count && *src; --count) {
+ s32 code = utf8_get(&src);
+
+ if (code < 0)
+ code = '?';
+ utf16_put(code, dst);
+ }
+ **dst = 0;
+ return 0;
+}
+
+s32 utf16_get(const u16 **src)
+{
+ s32 code, code2;
+
+ if (!src || !*src)
+ return -1;
+ if (!**src)
+ return 0;
+ code = **src;
+ ++*src;
+ if (code >= 0xDC00 && code <= 0xDFFF)
+ return -1;
+ if (code >= 0xD800 && code <= 0xDBFF) {
+ if (!**src)
+ return -1;
+ code &= 0x3ff;
+ code <<= 10;
+ code += 0x10000;
+ code2 = **src;
+ ++*src;
+ if (code2 <= 0xDC00 || code2 >= 0xDFFF)
+ return -1;
+ code2 &= 0x3ff;
+ code += code2;
+ }
+ return code;
+}
+
+int utf16_put(s32 code, u16 **dst)
+{
+ if (!dst || !*dst)
+ return -1;
+ if ((code >= 0xD800 && code <= 0xDFFF) || code >= 0x110000)
+ return -1;
+ if (code < 0x10000) {
+ **dst = code;
+ } else {
+ code -= 0x10000;
+ **dst = code >> 10 | 0xD800;
+ ++*dst;
+ **dst = (code & 0x3ff) | 0xDC00;
+ }
+ ++*dst;
+ return 0;
+}
+
+size_t utf16_strnlen(const u16 *src, size_t count)
+{
+ size_t len = 0;
+
+ for (; *src && count; --count) {
+ s32 code = utf16_get(&src);
+
+ if (!code)
+ break;
+ /*
+ * In case of an illegal sequence still reserve space for a
+ * replacement character.
+ */
+ ++len;
+ }
+ return len;
+}
+
+size_t utf16_utf8_strnlen(const u16 *src, size_t count)
+{
+ size_t len = 0;
+
+ for (; *src && count; --count) {
+ s32 code = utf16_get(&src);
+
+ if (!code)
+ break;
+ if (code < 0)
+ /* Reserve space for a replacement character */
+ len += 1;
+ else if (code < 0x80)
+ len += 1;
+ else if (code < 0x800)
+ len += 2;
+ else if (code < 0x10000)
+ len += 3;
+ else
+ len += 4;
+ }
+ return len;
+}
+
+int utf16_utf8_strncpy(char **dst, const u16 *src, size_t count)
+{
+ if (!src || !dst || !*dst)
+ return -1;
+
+ for (; count && *src; --count) {
+ s32 code = utf16_get(&src);
+
+ if (code < 0)
+ code = '?';
+ utf8_put(code, dst);
+ }
+ **dst = 0;
+ return 0;
+}
+
+s32 utf_to_lower(const s32 code)
+{
+ struct capitalization_table *pos = capitalization_table;
+ s32 ret = code;
+
+ if (code <= 0x7f) {
+ if (code >= 'A' && code <= 'Z')
+ ret += 0x20;
+ return ret;
+ }
+ for (; pos->upper; ++pos) {
+ if (pos->upper == code) {
+ ret = pos->lower;
+ break;
+ }
+ }
+ return ret;
+}
+
+s32 utf_to_upper(const s32 code)
+{
+ struct capitalization_table *pos = capitalization_table;
+ s32 ret = code;
+
+ if (code <= 0x7f) {
+ if (code >= 'a' && code <= 'z')
+ ret -= 0x20;
+ return ret;
+ }
+ for (; pos->lower; ++pos) {
+ if (pos->lower == code) {
+ ret = pos->upper;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
+ * u16_strncmp() - compare two u16 string
+ *
+ * @s1: first string to compare
+ * @s2: second string to compare
+ * @n: maximum number of u16 to compare
+ * Return: 0 if the first n u16 are the same in s1 and s2
+ * < 0 if the first different u16 in s1 is less than the
+ * corresponding u16 in s2
+ * > 0 if the first different u16 in s1 is greater than the
+ * corresponding u16 in s2
+ */
+int u16_strncmp(const u16 *s1, const u16 *s2, size_t n)
+{
+ int ret = 0;
+
+ for (; n; --n, ++s1, ++s2) {
+ ret = *s1 - *s2;
+ if (ret || !*s1)
+ break;
+ }
+
+ return ret;
+}
+
+size_t u16_strlen(const void *in)
+{
+ const char *pos = in;
+ size_t ret;
+
+ for (; pos[0] || pos[1]; pos += 2)
+ ;
+ ret = pos - (char *)in;
+ ret >>= 1;
+ return ret;
+}
+
+size_t u16_strnlen(const u16 *in, size_t count)
+{
+ size_t i;
+ for (i = 0; count-- && in[i]; i++);
+ return i;
+}
+
+u16 *u16_strcpy(u16 *dest, const u16 *src)
+{
+ u16 *tmp = dest;
+
+ for (;; dest++, src++) {
+ *dest = *src;
+ if (!*src)
+ break;
+ }
+
+ return tmp;
+}
+
+u16 *u16_strdup(const void *src)
+{
+ u16 *new;
+ size_t len;
+
+ if (!src)
+ return NULL;
+ len = (u16_strlen(src) + 1) * sizeof(u16);
+ new = malloc(len);
+ if (!new)
+ return NULL;
+ memcpy(new, src, len);
+
+ return new;
+}
+
+/* Convert UTF-16 to UTF-8. */
+uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size)
+{
+ uint32_t code_high = 0;
+
+ while (size--) {
+ uint32_t code = *src++;
+
+ if (code_high) {
+ if (code >= 0xDC00 && code <= 0xDFFF) {
+ /* Surrogate pair. */
+ code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x10000;
+
+ *dest++ = (code >> 18) | 0xF0;
+ *dest++ = ((code >> 12) & 0x3F) | 0x80;
+ *dest++ = ((code >> 6) & 0x3F) | 0x80;
+ *dest++ = (code & 0x3F) | 0x80;
+ } else {
+ /* Error... */
+ *dest++ = '?';
+ /* *src may be valid. Don't eat it. */
+ src--;
+ }
+
+ code_high = 0;
+ } else {
+ if (code <= 0x007F) {
+ *dest++ = code;
+ } else if (code <= 0x07FF) {
+ *dest++ = (code >> 6) | 0xC0;
+ *dest++ = (code & 0x3F) | 0x80;
+ } else if (code >= 0xD800 && code <= 0xDBFF) {
+ code_high = code;
+ continue;
+ } else if (code >= 0xDC00 && code <= 0xDFFF) {
+ /* Error... */
+ *dest++ = '?';
+ } else if (code < 0x10000) {
+ *dest++ = (code >> 12) | 0xE0;
+ *dest++ = ((code >> 6) & 0x3F) | 0x80;
+ *dest++ = (code & 0x3F) | 0x80;
+ } else {
+ *dest++ = (code >> 18) | 0xF0;
+ *dest++ = ((code >> 12) & 0x3F) | 0x80;
+ *dest++ = ((code >> 6) & 0x3F) | 0x80;
+ *dest++ = (code & 0x3F) | 0x80;
+ }
+ }
+ }
+
+ return dest;
+}
diff --git a/lib/circbuf.c b/lib/circbuf.c
new file mode 100644
index 00000000..071e4fb8
--- /dev/null
+++ b/lib/circbuf.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ */
+
+#include <common.h>
+#include <malloc.h>
+
+#include <circbuf.h>
+
+
+int buf_init (circbuf_t * buf, unsigned int size)
+{
+ assert (buf != NULL);
+
+ buf->size = 0;
+ buf->totalsize = size;
+ buf->data = (char *) malloc (sizeof (char) * size);
+ assert (buf->data != NULL);
+
+ buf->top = buf->data;
+ buf->tail = buf->data;
+ buf->end = &(buf->data[size]);
+
+ return 1;
+}
+
+int buf_free (circbuf_t * buf)
+{
+ assert (buf != NULL);
+ assert (buf->data != NULL);
+
+ free (buf->data);
+ memset (buf, 0, sizeof (circbuf_t));
+
+ return 1;
+}
+
+int buf_pop (circbuf_t * buf, char *dest, unsigned int len)
+{
+ unsigned int i;
+ char *p;
+
+ assert (buf != NULL);
+ assert (dest != NULL);
+
+ p = buf->top;
+
+ /* Cap to number of bytes in buffer */
+ if (len > buf->size)
+ len = buf->size;
+
+ for (i = 0; i < len; i++) {
+ dest[i] = *p++;
+ /* Bounds check. */
+ if (p == buf->end) {
+ p = buf->data;
+ }
+ }
+
+ /* Update 'top' pointer */
+ buf->top = p;
+ buf->size -= len;
+
+ return len;
+}
+
+int buf_push (circbuf_t * buf, const char *src, unsigned int len)
+{
+ /* NOTE: this function allows push to overwrite old data. */
+ unsigned int i;
+ char *p;
+
+ assert (buf != NULL);
+ assert (src != NULL);
+
+ p = buf->tail;
+
+ for (i = 0; i < len; i++) {
+ *p++ = src[i];
+ if (p == buf->end) {
+ p = buf->data;
+ }
+ /* Make sure pushing too much data just replaces old data */
+ if (buf->size < buf->totalsize) {
+ buf->size++;
+ } else {
+ buf->top++;
+ if (buf->top == buf->end) {
+ buf->top = buf->data;
+ }
+ }
+ }
+
+ /* Update 'tail' pointer */
+ buf->tail = p;
+
+ return len;
+}
diff --git a/lib/crc16.c b/lib/crc16.c
new file mode 100644
index 00000000..f46ba727
--- /dev/null
+++ b/lib/crc16.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: eCos-2.0
+/*
+ *==========================================================================
+ *
+ * crc16.c
+ *
+ * 16 bit CRC with polynomial x^16+x^12+x^5+1
+ *
+ *==========================================================================
+ *#####DESCRIPTIONBEGIN####
+ *
+ * Author(s): gthomas
+ * Contributors: gthomas,asl
+ * Date: 2001-01-31
+ * Purpose:
+ * Description:
+ *
+ * This code is part of eCos (tm).
+ *
+ *####DESCRIPTIONEND####
+ *
+ *==========================================================================
+ */
+
+#ifdef USE_HOSTCC
+#include <arpa/inet.h>
+#else
+#include <common.h>
+#endif
+#include <u-boot/crc.h>
+
+/* Table of CRC constants - implements x^16+x^12+x^5+1 */
+static const uint16_t crc16_tab[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
+};
+
+uint16_t crc16_ccitt(uint16_t cksum, const unsigned char *buf, int len)
+{
+ for (int i = 0; i < len; i++)
+ cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xff] ^ (cksum << 8);
+
+ return cksum;
+}
+
+void crc16_ccitt_wd_buf(const uint8_t *in, uint len,
+ uint8_t *out, uint chunk_sz)
+{
+ uint16_t crc;
+
+ crc = crc16_ccitt(0, in, len);
+ crc = htons(crc);
+ memcpy(out, &crc, sizeof(crc));
+}
diff --git a/lib/crc32.c b/lib/crc32.c
new file mode 100644
index 00000000..e9be3bf3
--- /dev/null
+++ b/lib/crc32.c
@@ -0,0 +1,267 @@
+/*
+ * This file is derived from crc32.c from the zlib-1.1.3 distribution
+ * by Jean-loup Gailly and Mark Adler.
+ */
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef USE_HOSTCC
+#include <arpa/inet.h>
+#include <u-boot/crc.h>
+#else
+#include <common.h>
+#include <efi_loader.h>
+#endif
+#include <compiler.h>
+#include <u-boot/crc.h>
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+#include <watchdog.h>
+#endif
+#include "u-boot/zlib.h"
+
+#ifdef USE_HOSTCC
+#define __efi_runtime
+#define __efi_runtime_data
+#endif
+
+#define tole(x) cpu_to_le32(x)
+
+#ifdef CONFIG_DYNAMIC_CRC_TABLE
+
+static int __efi_runtime_data crc_table_empty = 1;
+static uint32_t __efi_runtime_data crc_table[256];
+static void __efi_runtime make_crc_table OF((void));
+
+/*
+ Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all
+ the information needed to generate CRC's on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+*/
+static void __efi_runtime make_crc_table(void)
+{
+ uint32_t c;
+ int n, k;
+ uLong poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static Byte __efi_runtime_data p[] = {
+ 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26};
+
+ /* make exclusive-or pattern from polynomial (0xedb88320L) */
+ poly = 0L;
+ for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+ poly |= 1L << (31 - p[n]);
+
+ for (n = 0; n < 256; n++)
+ {
+ c = (uLong)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[n] = tole(c);
+ }
+ crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+
+static const uint32_t __efi_runtime_data crc_table[256] = {
+tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
+tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
+tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
+tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
+tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
+tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
+tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
+tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
+tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
+tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
+tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
+tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
+tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
+tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
+tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
+tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
+tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
+tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
+tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
+tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
+tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
+tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
+tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
+tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
+tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
+tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
+tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
+tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
+tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
+tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
+tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
+tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
+tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
+tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
+tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
+tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
+tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
+tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
+tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
+tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
+tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
+tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
+tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
+tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
+tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
+tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
+tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
+tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
+tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
+tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
+tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
+tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
+tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
+tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
+tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
+tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
+tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
+tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
+tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
+tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
+tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
+tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
+tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
+tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
+};
+#endif
+
+#if 0
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const uint32_t * ZEXPORT get_crc_table()
+{
+#ifdef CONFIG_DYNAMIC_CRC_TABLE
+ if (crc_table_empty) make_crc_table();
+#endif
+ return (const uint32_t *)crc_table;
+}
+#endif
+
+/* ========================================================================= */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
+# else
+# define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
+# endif
+
+/* ========================================================================= */
+
+/* No ones complement version. JFFS2 (and other things ?)
+ * don't use ones compliment in their CRC calculations.
+ */
+uint32_t __efi_runtime crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len)
+{
+ const uint32_t *tab = crc_table;
+ const uint32_t *b =(const uint32_t *)buf;
+ size_t rem_len;
+#ifdef CONFIG_DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif
+ crc = cpu_to_le32(crc);
+ /* Align it */
+ if (((long)b) & 3 && len) {
+ uint8_t *p = (uint8_t *)b;
+ do {
+ DO_CRC(*p++);
+ } while ((--len) && ((long)p)&3);
+ b = (uint32_t *)p;
+ }
+
+ rem_len = len & 3;
+ len = len >> 2;
+ for (--b; len; --len) {
+ /* load data 32 bits wide, xor data 32 bits wide. */
+ crc ^= *++b; /* use pre increment for speed */
+ DO_CRC(0);
+ DO_CRC(0);
+ DO_CRC(0);
+ DO_CRC(0);
+ }
+ len = rem_len;
+ /* And the last few bytes */
+ if (len) {
+ uint8_t *p = (uint8_t *)(b + 1) - 1;
+ do {
+ DO_CRC(*++p); /* use pre increment for speed */
+ } while (--len);
+ }
+
+ return le32_to_cpu(crc);
+}
+#undef DO_CRC
+
+uint32_t __efi_runtime crc32(uint32_t crc, const Bytef *p, uInt len)
+{
+ return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
+}
+
+/*
+ * Calculate the crc32 checksum triggering the watchdog every 'chunk_sz' bytes
+ * of input.
+ */
+uint32_t crc32_wd(uint32_t crc, const unsigned char *buf, uInt len,
+ uInt chunk_sz)
+{
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ const unsigned char *end, *curr;
+ int chunk;
+
+ curr = buf;
+ end = buf + len;
+ while (curr < end) {
+ chunk = end - curr;
+ if (chunk > chunk_sz)
+ chunk = chunk_sz;
+ crc = crc32(crc, curr, chunk);
+ curr += chunk;
+ WATCHDOG_RESET ();
+ }
+#else
+ crc = crc32(crc, buf, len);
+#endif
+
+ return crc;
+}
+
+void crc32_wd_buf(const unsigned char *input, unsigned int ilen,
+ unsigned char *output, unsigned int chunk_sz)
+{
+ uint32_t crc;
+
+ crc = crc32_wd(0, input, ilen, chunk_sz);
+ crc = htonl(crc);
+ memcpy(output, &crc, sizeof(crc));
+}
diff --git a/lib/crc32c.c b/lib/crc32c.c
new file mode 100644
index 00000000..016b34a5
--- /dev/null
+++ b/lib/crc32c.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copied from Linux kernel crypto/crc32c.c
+ * Copyright (c) 2004 Cisco Systems, Inc.
+ * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <compiler.h>
+
+uint32_t crc32c_cal(uint32_t crc, const char *data, int length,
+ uint32_t *crc32c_table)
+{
+ while (length--)
+ crc = crc32c_table[(u8)(crc ^ *data++)] ^ (crc >> 8);
+
+ return crc;
+}
+
+void crc32c_init(uint32_t *crc32c_table, uint32_t pol)
+{
+ int i, j;
+ uint32_t v;
+ const uint32_t poly = pol; /* Bit-reflected CRC32C polynomial */
+
+ for (i = 0; i < 256; i++) {
+ v = i;
+ for (j = 0; j < 8; j++)
+ v = (v >> 1) ^ ((v & 1) ? poly : 0);
+
+ crc32c_table[i] = v;
+ }
+}
diff --git a/lib/crc7.c b/lib/crc7.c
new file mode 100644
index 00000000..e635c9c2
--- /dev/null
+++ b/lib/crc7.c
@@ -0,0 +1,62 @@
+/*
+ * crc7.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/crc7.h>
+
+
+/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
+const u8 crc7_syndrome_table[256] = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+ 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+ 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+ 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+ 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+ 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+ 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+ 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+ 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+ 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+ 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+ 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+ 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+ 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+ 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+ 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+ 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+ 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+ 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+ 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+ 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+ 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+ 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+ 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+ 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+ 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+ 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+ 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+ 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+ 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+
+/**
+ * crc7 - update the CRC7 for the data buffer
+ * @crc: previous CRC7 value
+ * @buffer: data pointer
+ * @len: number of bytes in the buffer
+ * Context: any
+ *
+ * Returns the updated CRC7 value.
+ */
+u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+ while (len--)
+ crc = crc7_byte(crc, *buffer++);
+ return crc;
+}
diff --git a/lib/crc8.c b/lib/crc8.c
new file mode 100644
index 00000000..87b87b67
--- /dev/null
+++ b/lib/crc8.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 Google, Inc
+ */
+
+#ifdef USE_HOSTCC
+#include <arpa/inet.h>
+#else
+#include <common.h>
+#endif
+#include <u-boot/crc.h>
+
+#define POLY (0x1070U << 3)
+
+static unsigned char _crc8(unsigned short data)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (data & 0x8000)
+ data = data ^ POLY;
+ data = data << 1;
+ }
+
+ return (unsigned char)(data >> 8);
+}
+
+unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ crc = _crc8((crc ^ vptr[i]) << 8);
+
+ return crc;
+}
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
new file mode 100644
index 00000000..2b221b91
--- /dev/null
+++ b/lib/crypto/Kconfig
@@ -0,0 +1,52 @@
+menuconfig ASYMMETRIC_KEY_TYPE
+ bool "Asymmetric (public-key cryptographic) key Support"
+ help
+ This option provides support for a key type that holds the data for
+ the asymmetric keys used for public key cryptographic operations such
+ as encryption, decryption, signature generation and signature
+ verification.
+
+if ASYMMETRIC_KEY_TYPE
+
+config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+ bool "Asymmetric public-key crypto algorithm subtype"
+ help
+ This option provides support for asymmetric public key type handling.
+ If signature generation and/or verification are to be used,
+ appropriate hash algorithms (such as SHA-1) must be available.
+ ENOPKG will be reported if the requisite algorithm is unavailable.
+
+config RSA_PUBLIC_KEY_PARSER
+ bool "RSA public key parser"
+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+ select ASN1_DECODER
+ select ASN1_COMPILER
+ select OID_REGISTRY
+ help
+ This option provides support for parsing a blob containing RSA
+ public key data and provides the ability to instantiate a public
+ key.
+
+config X509_CERTIFICATE_PARSER
+ bool "X.509 certificate parser"
+ depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+ select ASN1_DECODER
+ select ASN1_COMPILER
+ select OID_REGISTRY
+ select LIB_DATE
+ help
+ This option provides support for parsing X.509 format blobs for key
+ data and provides the ability to instantiate a crypto key from a
+ public key packet found inside the certificate.
+
+config PKCS7_MESSAGE_PARSER
+ bool "PKCS#7 message parser"
+ depends on X509_CERTIFICATE_PARSER
+ select ASN1_DECODER
+ select ASN1_COMPILER
+ select OID_REGISTRY
+ help
+ This option provides support for parsing PKCS#7 format messages for
+ signature data and provides the ability to verify the signature.
+
+endif # ASYMMETRIC_KEY_TYPE
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
new file mode 100644
index 00000000..8267fee0
--- /dev/null
+++ b/lib/crypto/Makefile
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Makefile for asymmetric cryptographic keys
+#
+
+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+
+asymmetric_keys-y := asymmetric_type.o
+
+obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
+
+#
+# RSA public key parser
+#
+obj-$(CONFIG_RSA_PUBLIC_KEY_PARSER) += rsa_public_key.o
+rsa_public_key-y := \
+ rsapubkey.asn1.o \
+ rsa_helper.o
+
+$(obj)/rsapubkey.asn1.o: $(obj)/rsapubkey.asn1.c $(obj)/rsapubkey.asn1.h
+$(obj)/rsa_helper.o: $(obj)/rsapubkey.asn1.h
+
+#
+# X.509 Certificate handling
+#
+obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
+x509_key_parser-y := \
+ x509.asn1.o \
+ x509_akid.asn1.o \
+ x509_cert_parser.o \
+ x509_public_key.o
+
+$(obj)/x509_cert_parser.o: \
+ $(obj)/x509.asn1.h \
+ $(obj)/x509_akid.asn1.h
+
+$(obj)/x509.asn1.o: $(obj)/x509.asn1.c $(obj)/x509.asn1.h
+$(obj)/x509_akid.asn1.o: $(obj)/x509_akid.asn1.c $(obj)/x509_akid.asn1.h
+
+#
+# PKCS#7 message handling
+#
+obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
+pkcs7_message-y := \
+ pkcs7.asn1.o \
+ pkcs7_parser.o
+
+$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h
+$(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h
diff --git a/lib/crypto/asymmetric_type.c b/lib/crypto/asymmetric_type.c
new file mode 100644
index 00000000..e04666c0
--- /dev/null
+++ b/lib/crypto/asymmetric_type.c
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Asymmetric public-key cryptography key type
+ *
+ * See Documentation/crypto/asymmetric-keys.txt
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#ifndef __UBOOT__
+#include <keys/asymmetric-subtype.h>
+#include <keys/asymmetric-parser.h>
+#endif
+#include <crypto/public_key.h>
+#ifdef __UBOOT__
+#include <linux/compat.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#else
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#endif
+#ifdef __UBOOT__
+#include <keys/asymmetric-type.h>
+#else
+#include <keys/system_keyring.h>
+#include <keys/user-type.h>
+#include "asymmetric_keys.h"
+#endif
+
+MODULE_LICENSE("GPL");
+
+#ifndef __UBOOT__
+const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = {
+ [VERIFYING_MODULE_SIGNATURE] = "mod sig",
+ [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig",
+ [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig",
+ [VERIFYING_KEY_SIGNATURE] = "key sig",
+ [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig",
+ [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig",
+};
+EXPORT_SYMBOL_GPL(key_being_used_for);
+
+static LIST_HEAD(asymmetric_key_parsers);
+static DECLARE_RWSEM(asymmetric_key_parsers_sem);
+
+/**
+ * find_asymmetric_key - Find a key by ID.
+ * @keyring: The keys to search.
+ * @id_0: The first ID to look for or NULL.
+ * @id_1: The second ID to look for or NULL.
+ * @partial: Use partial match if true, exact if false.
+ *
+ * Find a key in the given keyring by identifier. The preferred identifier is
+ * the id_0 and the fallback identifier is the id_1. If both are given, the
+ * lookup is by the former, but the latter must also match.
+ */
+struct key *find_asymmetric_key(struct key *keyring,
+ const struct asymmetric_key_id *id_0,
+ const struct asymmetric_key_id *id_1,
+ bool partial)
+{
+ struct key *key;
+ key_ref_t ref;
+ const char *lookup;
+ char *req, *p;
+ int len;
+
+ BUG_ON(!id_0 && !id_1);
+
+ if (id_0) {
+ lookup = id_0->data;
+ len = id_0->len;
+ } else {
+ lookup = id_1->data;
+ len = id_1->len;
+ }
+
+ /* Construct an identifier "id:<keyid>". */
+ p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
+ if (!req)
+ return ERR_PTR(-ENOMEM);
+
+ if (partial) {
+ *p++ = 'i';
+ *p++ = 'd';
+ } else {
+ *p++ = 'e';
+ *p++ = 'x';
+ }
+ *p++ = ':';
+ p = bin2hex(p, lookup, len);
+ *p = 0;
+
+ pr_debug("Look up: \"%s\"\n", req);
+
+ ref = keyring_search(make_key_ref(keyring, 1),
+ &key_type_asymmetric, req, true);
+ if (IS_ERR(ref))
+ pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
+ kfree(req);
+
+ if (IS_ERR(ref)) {
+ switch (PTR_ERR(ref)) {
+ /* Hide some search errors */
+ case -EACCES:
+ case -ENOTDIR:
+ case -EAGAIN:
+ return ERR_PTR(-ENOKEY);
+ default:
+ return ERR_CAST(ref);
+ }
+ }
+
+ key = key_ref_to_ptr(ref);
+ if (id_0 && id_1) {
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+
+ if (!kids->id[1]) {
+ pr_debug("First ID matches, but second is missing\n");
+ goto reject;
+ }
+ if (!asymmetric_key_id_same(id_1, kids->id[1])) {
+ pr_debug("First ID matches, but second does not\n");
+ goto reject;
+ }
+ }
+
+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
+ return key;
+
+reject:
+ key_put(key);
+ return ERR_PTR(-EKEYREJECTED);
+}
+EXPORT_SYMBOL_GPL(find_asymmetric_key);
+#endif /* !__UBOOT__ */
+
+/**
+ * asymmetric_key_generate_id: Construct an asymmetric key ID
+ * @val_1: First binary blob
+ * @len_1: Length of first binary blob
+ * @val_2: Second binary blob
+ * @len_2: Length of second binary blob
+ *
+ * Construct an asymmetric key ID from a pair of binary blobs.
+ */
+struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
+ size_t len_1,
+ const void *val_2,
+ size_t len_2)
+{
+ struct asymmetric_key_id *kid;
+
+ kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
+ GFP_KERNEL);
+ if (!kid)
+ return ERR_PTR(-ENOMEM);
+ kid->len = len_1 + len_2;
+ memcpy(kid->data, val_1, len_1);
+ memcpy(kid->data + len_1, val_2, len_2);
+ return kid;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_generate_id);
+
+/**
+ * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same.
+ * @kid_1, @kid_2: The key IDs to compare
+ */
+bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2)
+{
+ if (!kid1 || !kid2)
+ return false;
+ if (kid1->len != kid2->len)
+ return false;
+ return memcmp(kid1->data, kid2->data, kid1->len) == 0;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
+
+/**
+ * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
+ * partially match
+ * @kid_1, @kid_2: The key IDs to compare
+ */
+bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2)
+{
+ if (!kid1 || !kid2)
+ return false;
+ if (kid1->len < kid2->len)
+ return false;
+ return memcmp(kid1->data + (kid1->len - kid2->len),
+ kid2->data, kid2->len) == 0;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
+
+#ifndef __UBOOT__
+/**
+ * asymmetric_match_key_ids - Search asymmetric key IDs
+ * @kids: The list of key IDs to check
+ * @match_id: The key ID we're looking for
+ * @match: The match function to use
+ */
+static bool asymmetric_match_key_ids(
+ const struct asymmetric_key_ids *kids,
+ const struct asymmetric_key_id *match_id,
+ bool (*match)(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2))
+{
+ int i;
+
+ if (!kids || !match_id)
+ return false;
+ for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+ if (match(kids->id[i], match_id))
+ return true;
+ return false;
+}
+
+/* helper function can be called directly with pre-allocated memory */
+inline int __asymmetric_key_hex_to_key_id(const char *id,
+ struct asymmetric_key_id *match_id,
+ size_t hexlen)
+{
+ match_id->len = hexlen;
+ return hex2bin(match_id->data, id, hexlen);
+}
+
+/**
+ * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
+ * @id: The ID as a hex string.
+ */
+struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
+{
+ struct asymmetric_key_id *match_id;
+ size_t asciihexlen;
+ int ret;
+
+ if (!*id)
+ return ERR_PTR(-EINVAL);
+ asciihexlen = strlen(id);
+ if (asciihexlen & 1)
+ return ERR_PTR(-EINVAL);
+
+ match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2,
+ GFP_KERNEL);
+ if (!match_id)
+ return ERR_PTR(-ENOMEM);
+ ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2);
+ if (ret < 0) {
+ kfree(match_id);
+ return ERR_PTR(-EINVAL);
+ }
+ return match_id;
+}
+
+/*
+ * Match asymmetric keys by an exact match on an ID.
+ */
+static bool asymmetric_key_cmp(const struct key *key,
+ const struct key_match_data *match_data)
+{
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *match_id = match_data->preparsed;
+
+ return asymmetric_match_key_ids(kids, match_id,
+ asymmetric_key_id_same);
+}
+
+/*
+ * Match asymmetric keys by a partial match on an IDs.
+ */
+static bool asymmetric_key_cmp_partial(const struct key *key,
+ const struct key_match_data *match_data)
+{
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *match_id = match_data->preparsed;
+
+ return asymmetric_match_key_ids(kids, match_id,
+ asymmetric_key_id_partial);
+}
+
+/*
+ * Preparse the match criterion. If we don't set lookup_type and cmp,
+ * the default will be an exact match on the key description.
+ *
+ * There are some specifiers for matching key IDs rather than by the key
+ * description:
+ *
+ * "id:<id>" - find a key by partial match on any available ID
+ * "ex:<id>" - find a key by exact match on any available ID
+ *
+ * These have to be searched by iteration rather than by direct lookup because
+ * the key is hashed according to its description.
+ */
+static int asymmetric_key_match_preparse(struct key_match_data *match_data)
+{
+ struct asymmetric_key_id *match_id;
+ const char *spec = match_data->raw_data;
+ const char *id;
+ bool (*cmp)(const struct key *, const struct key_match_data *) =
+ asymmetric_key_cmp;
+
+ if (!spec || !*spec)
+ return -EINVAL;
+ if (spec[0] == 'i' &&
+ spec[1] == 'd' &&
+ spec[2] == ':') {
+ id = spec + 3;
+ cmp = asymmetric_key_cmp_partial;
+ } else if (spec[0] == 'e' &&
+ spec[1] == 'x' &&
+ spec[2] == ':') {
+ id = spec + 3;
+ } else {
+ goto default_match;
+ }
+
+ match_id = asymmetric_key_hex_to_key_id(id);
+ if (IS_ERR(match_id))
+ return PTR_ERR(match_id);
+
+ match_data->preparsed = match_id;
+ match_data->cmp = cmp;
+ match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
+ return 0;
+
+default_match:
+ return 0;
+}
+
+/*
+ * Free the preparsed the match criterion.
+ */
+static void asymmetric_key_match_free(struct key_match_data *match_data)
+{
+ kfree(match_data->preparsed);
+}
+
+/*
+ * Describe the asymmetric key
+ */
+static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
+{
+ const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *kid;
+ const unsigned char *p;
+ int n;
+
+ seq_puts(m, key->description);
+
+ if (subtype) {
+ seq_puts(m, ": ");
+ subtype->describe(key, m);
+
+ if (kids && kids->id[1]) {
+ kid = kids->id[1];
+ seq_putc(m, ' ');
+ n = kid->len;
+ p = kid->data;
+ if (n > 4) {
+ p += n - 4;
+ n = 4;
+ }
+ seq_printf(m, "%*phN", n, p);
+ }
+
+ seq_puts(m, " [");
+ /* put something here to indicate the key's capabilities */
+ seq_putc(m, ']');
+ }
+}
+
+/*
+ * Preparse a asymmetric payload to get format the contents appropriately for the
+ * internal payload to cut down on the number of scans of the data performed.
+ *
+ * We also generate a proposed description from the contents of the key that
+ * can be used to name the key if the user doesn't want to provide one.
+ */
+static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
+{
+ struct asymmetric_key_parser *parser;
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (prep->datalen == 0)
+ return -EINVAL;
+
+ down_read(&asymmetric_key_parsers_sem);
+
+ ret = -EBADMSG;
+ list_for_each_entry(parser, &asymmetric_key_parsers, link) {
+ pr_debug("Trying parser '%s'\n", parser->name);
+
+ ret = parser->parse(prep);
+ if (ret != -EBADMSG) {
+ pr_debug("Parser recognised the format (ret %d)\n",
+ ret);
+ break;
+ }
+ }
+
+ up_read(&asymmetric_key_parsers_sem);
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+}
+
+/*
+ * Clean up the key ID list
+ */
+static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
+{
+ int i;
+
+ if (kids) {
+ for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+ kfree(kids->id[i]);
+ kfree(kids);
+ }
+}
+
+/*
+ * Clean up the preparse data
+ */
+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
+{
+ struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
+ struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (subtype) {
+ subtype->destroy(prep->payload.data[asym_crypto],
+ prep->payload.data[asym_auth]);
+ module_put(subtype->owner);
+ }
+ asymmetric_key_free_kids(kids);
+ kfree(prep->description);
+}
+
+/*
+ * dispose of the data dangling from the corpse of a asymmetric key
+ */
+static void asymmetric_key_destroy(struct key *key)
+{
+ struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
+ struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
+ void *data = key->payload.data[asym_crypto];
+ void *auth = key->payload.data[asym_auth];
+
+ key->payload.data[asym_crypto] = NULL;
+ key->payload.data[asym_subtype] = NULL;
+ key->payload.data[asym_key_ids] = NULL;
+ key->payload.data[asym_auth] = NULL;
+
+ if (subtype) {
+ subtype->destroy(data, auth);
+ module_put(subtype->owner);
+ }
+
+ asymmetric_key_free_kids(kids);
+}
+
+static struct key_restriction *asymmetric_restriction_alloc(
+ key_restrict_link_func_t check,
+ struct key *key)
+{
+ struct key_restriction *keyres =
+ kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
+
+ if (!keyres)
+ return ERR_PTR(-ENOMEM);
+
+ keyres->check = check;
+ keyres->key = key;
+ keyres->keytype = &key_type_asymmetric;
+
+ return keyres;
+}
+
+/*
+ * look up keyring restrict functions for asymmetric keys
+ */
+static struct key_restriction *asymmetric_lookup_restriction(
+ const char *restriction)
+{
+ char *restrict_method;
+ char *parse_buf;
+ char *next;
+ struct key_restriction *ret = ERR_PTR(-EINVAL);
+
+ if (strcmp("builtin_trusted", restriction) == 0)
+ return asymmetric_restriction_alloc(
+ restrict_link_by_builtin_trusted, NULL);
+
+ if (strcmp("builtin_and_secondary_trusted", restriction) == 0)
+ return asymmetric_restriction_alloc(
+ restrict_link_by_builtin_and_secondary_trusted, NULL);
+
+ parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
+ if (!parse_buf)
+ return ERR_PTR(-ENOMEM);
+
+ next = parse_buf;
+ restrict_method = strsep(&next, ":");
+
+ if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
+ char *key_text;
+ key_serial_t serial;
+ struct key *key;
+ key_restrict_link_func_t link_fn =
+ restrict_link_by_key_or_keyring;
+ bool allow_null_key = false;
+
+ key_text = strsep(&next, ":");
+
+ if (next) {
+ if (strcmp(next, "chain") != 0)
+ goto out;
+
+ link_fn = restrict_link_by_key_or_keyring_chain;
+ allow_null_key = true;
+ }
+
+ if (kstrtos32(key_text, 0, &serial) < 0)
+ goto out;
+
+ if ((serial == 0) && allow_null_key) {
+ key = NULL;
+ } else {
+ key = key_lookup(serial);
+ if (IS_ERR(key)) {
+ ret = ERR_CAST(key);
+ goto out;
+ }
+ }
+
+ ret = asymmetric_restriction_alloc(link_fn, key);
+ if (IS_ERR(ret))
+ key_put(key);
+ }
+
+out:
+ kfree(parse_buf);
+ return ret;
+}
+
+int asymmetric_key_eds_op(struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ const struct asymmetric_key_subtype *subtype;
+ struct key *key = params->key;
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (key->type != &key_type_asymmetric)
+ return -EINVAL;
+ subtype = asymmetric_key_subtype(key);
+ if (!subtype ||
+ !key->payload.data[0])
+ return -EINVAL;
+ if (!subtype->eds_op)
+ return -ENOTSUPP;
+
+ ret = subtype->eds_op(params, in, out);
+
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static int asymmetric_key_verify_signature(struct kernel_pkey_params *params,
+ const void *in, const void *in2)
+{
+ struct public_key_signature sig = {
+ .s_size = params->in2_len,
+ .digest_size = params->in_len,
+ .encoding = params->encoding,
+ .hash_algo = params->hash_algo,
+ .digest = (void *)in,
+ .s = (void *)in2,
+ };
+
+ return verify_signature(params->key, &sig);
+}
+
+struct key_type key_type_asymmetric = {
+ .name = "asymmetric",
+ .preparse = asymmetric_key_preparse,
+ .free_preparse = asymmetric_key_free_preparse,
+ .instantiate = generic_key_instantiate,
+ .match_preparse = asymmetric_key_match_preparse,
+ .match_free = asymmetric_key_match_free,
+ .destroy = asymmetric_key_destroy,
+ .describe = asymmetric_key_describe,
+ .lookup_restriction = asymmetric_lookup_restriction,
+ .asym_query = query_asymmetric_key,
+ .asym_eds_op = asymmetric_key_eds_op,
+ .asym_verify_signature = asymmetric_key_verify_signature,
+};
+EXPORT_SYMBOL_GPL(key_type_asymmetric);
+
+/**
+ * register_asymmetric_key_parser - Register a asymmetric key blob parser
+ * @parser: The parser to register
+ */
+int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
+{
+ struct asymmetric_key_parser *cursor;
+ int ret;
+
+ down_write(&asymmetric_key_parsers_sem);
+
+ list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
+ if (strcmp(cursor->name, parser->name) == 0) {
+ pr_err("Asymmetric key parser '%s' already registered\n",
+ parser->name);
+ ret = -EEXIST;
+ goto out;
+ }
+ }
+
+ list_add_tail(&parser->link, &asymmetric_key_parsers);
+
+ pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
+ ret = 0;
+
+out:
+ up_write(&asymmetric_key_parsers_sem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
+
+/**
+ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
+ * @parser: The parser to unregister
+ */
+void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
+{
+ down_write(&asymmetric_key_parsers_sem);
+ list_del(&parser->link);
+ up_write(&asymmetric_key_parsers_sem);
+
+ pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
+}
+EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
+
+/*
+ * Module stuff
+ */
+static int __init asymmetric_key_init(void)
+{
+ return register_key_type(&key_type_asymmetric);
+}
+
+static void __exit asymmetric_key_cleanup(void)
+{
+ unregister_key_type(&key_type_asymmetric);
+}
+
+module_init(asymmetric_key_init);
+module_exit(asymmetric_key_cleanup);
+#endif /* !__UBOOT__ */
diff --git a/lib/crypto/pkcs7.asn1 b/lib/crypto/pkcs7.asn1
new file mode 100644
index 00000000..1eca740b
--- /dev/null
+++ b/lib/crypto/pkcs7.asn1
@@ -0,0 +1,135 @@
+PKCS7ContentInfo ::= SEQUENCE {
+ contentType ContentType ({ pkcs7_check_content_type }),
+ content [0] EXPLICIT SignedData OPTIONAL
+}
+
+ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID })
+
+SignedData ::= SEQUENCE {
+ version INTEGER ({ pkcs7_note_signeddata_version }),
+ digestAlgorithms DigestAlgorithmIdentifiers,
+ contentInfo ContentInfo ({ pkcs7_note_content }),
+ certificates CHOICE {
+ certSet [0] IMPLICIT ExtendedCertificatesAndCertificates,
+ certSequence [2] IMPLICIT Certificates
+ } OPTIONAL ({ pkcs7_note_certificate_list }),
+ crls CHOICE {
+ crlSet [1] IMPLICIT CertificateRevocationLists,
+ crlSequence [3] IMPLICIT CRLSequence
+ } OPTIONAL,
+ signerInfos SignerInfos
+}
+
+ContentInfo ::= SEQUENCE {
+ contentType ContentType ({ pkcs7_note_OID }),
+ content [0] EXPLICIT Data OPTIONAL
+}
+
+Data ::= ANY ({ pkcs7_note_data })
+
+DigestAlgorithmIdentifiers ::= CHOICE {
+ daSet SET OF DigestAlgorithmIdentifier,
+ daSequence SEQUENCE OF DigestAlgorithmIdentifier
+}
+
+DigestAlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ parameters ANY OPTIONAL
+}
+
+--
+-- Certificates and certificate lists
+--
+ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate
+
+ExtendedCertificateOrCertificate ::= CHOICE {
+ certificate Certificate, -- X.509
+ extendedCertificate [0] IMPLICIT ExtendedCertificate -- PKCS#6
+}
+
+ExtendedCertificate ::= Certificate -- cheating
+
+Certificates ::= SEQUENCE OF Certificate
+
+CertificateRevocationLists ::= SET OF CertificateList
+
+CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly
+
+CRLSequence ::= SEQUENCE OF CertificateList
+
+Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509
+
+--
+-- Signer information
+--
+SignerInfos ::= CHOICE {
+ siSet SET OF SignerInfo,
+ siSequence SEQUENCE OF SignerInfo
+}
+
+SignerInfo ::= SEQUENCE {
+ version INTEGER ({ pkcs7_note_signerinfo_version }),
+ sid SignerIdentifier, -- CMS variant, not PKCS#7
+ digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
+ authenticatedAttributes CHOICE {
+ aaSet [0] IMPLICIT SetOfAuthenticatedAttribute
+ ({ pkcs7_sig_note_set_of_authattrs }),
+ aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
+ -- Explicit because easier to compute digest on
+ -- sequence of attributes and then reuse encoded
+ -- sequence in aaSequence.
+ } OPTIONAL,
+ digestEncryptionAlgorithm
+ DigestEncryptionAlgorithmIdentifier ({ pkcs7_sig_note_pkey_algo }),
+ encryptedDigest EncryptedDigest,
+ unauthenticatedAttributes CHOICE {
+ uaSet [1] IMPLICIT SET OF UnauthenticatedAttribute,
+ uaSequence [3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute
+ } OPTIONAL
+} ({ pkcs7_note_signed_info })
+
+SignerIdentifier ::= CHOICE {
+ -- RFC5652 sec 5.3
+ issuerAndSerialNumber IssuerAndSerialNumber,
+ subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier
+}
+
+IssuerAndSerialNumber ::= SEQUENCE {
+ issuer Name ({ pkcs7_sig_note_issuer }),
+ serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial })
+}
+
+CertificateSerialNumber ::= INTEGER
+
+SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid })
+
+SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
+
+AuthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ values SET OF ANY ({ pkcs7_sig_note_authenticated_attr })
+}
+
+UnauthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER,
+ values SET OF ANY
+}
+
+DigestEncryptionAlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ parameters ANY OPTIONAL
+}
+
+EncryptedDigest ::= OCTET STRING ({ pkcs7_sig_note_signature })
+
+---
+--- X.500 Name
+---
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeType OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ attributeValue ANY
+}
diff --git a/lib/crypto/pkcs7_parser.c b/lib/crypto/pkcs7_parser.c
new file mode 100644
index 00000000..bf9e7e88
--- /dev/null
+++ b/lib/crypto/pkcs7_parser.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* PKCS#7 parser
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#ifdef __UBOOT__
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#endif
+#include <linux/kernel.h>
+#ifndef __UBOOT__
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#endif
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#include <crypto/public_key.h>
+#include "pkcs7_parser.h"
+#include "pkcs7.asn1.h"
+
+MODULE_DESCRIPTION("PKCS#7 parser");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
+struct pkcs7_parse_context {
+ struct pkcs7_message *msg; /* Message being constructed */
+ struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */
+ struct pkcs7_signed_info **ppsinfo;
+ struct x509_certificate *certs; /* Certificate cache */
+ struct x509_certificate **ppcerts;
+ unsigned long data; /* Start of data */
+ enum OID last_oid; /* Last OID encountered */
+ unsigned x509_index;
+ unsigned sinfo_index;
+ const void *raw_serial;
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer;
+ const void *raw_skid;
+ unsigned raw_skid_size;
+ bool expect_skid;
+};
+
+/*
+ * Free a signed information block.
+ */
+static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
+{
+ if (sinfo) {
+ public_key_signature_free(sinfo->sig);
+ kfree(sinfo);
+ }
+}
+
+/**
+ * pkcs7_free_message - Free a PKCS#7 message
+ * @pkcs7: The PKCS#7 message to free
+ */
+void pkcs7_free_message(struct pkcs7_message *pkcs7)
+{
+ struct x509_certificate *cert;
+ struct pkcs7_signed_info *sinfo;
+
+ if (pkcs7) {
+ while (pkcs7->certs) {
+ cert = pkcs7->certs;
+ pkcs7->certs = cert->next;
+ x509_free_certificate(cert);
+ }
+ while (pkcs7->crl) {
+ cert = pkcs7->crl;
+ pkcs7->crl = cert->next;
+ x509_free_certificate(cert);
+ }
+ while (pkcs7->signed_infos) {
+ sinfo = pkcs7->signed_infos;
+ pkcs7->signed_infos = sinfo->next;
+ pkcs7_free_signed_info(sinfo);
+ }
+ kfree(pkcs7);
+ }
+}
+EXPORT_SYMBOL_GPL(pkcs7_free_message);
+
+/*
+ * Check authenticatedAttributes are provided or not provided consistently.
+ */
+static int pkcs7_check_authattrs(struct pkcs7_message *msg)
+{
+ struct pkcs7_signed_info *sinfo;
+ bool want = false;
+
+ sinfo = msg->signed_infos;
+ if (!sinfo)
+ goto inconsistent;
+
+ if (sinfo->authattrs) {
+ want = true;
+ msg->have_authattrs = true;
+ }
+
+ for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next)
+ if (!!sinfo->authattrs != want)
+ goto inconsistent;
+ return 0;
+
+inconsistent:
+ pr_warn("Inconsistently supplied authAttrs\n");
+ return -EINVAL;
+}
+
+/**
+ * pkcs7_parse_message - Parse a PKCS#7 message
+ * @data: The raw binary ASN.1 encoded message to be parsed
+ * @datalen: The size of the encoded message
+ */
+struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
+{
+ struct pkcs7_parse_context *ctx;
+ struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
+ int ret;
+
+ ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
+ if (!ctx)
+ goto out_no_ctx;
+ ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
+ if (!ctx->msg)
+ goto out_no_msg;
+ ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+ if (!ctx->sinfo)
+ goto out_no_sinfo;
+ ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
+ GFP_KERNEL);
+ if (!ctx->sinfo->sig)
+ goto out_no_sig;
+
+ ctx->data = (unsigned long)data;
+ ctx->ppcerts = &ctx->certs;
+ ctx->ppsinfo = &ctx->msg->signed_infos;
+
+ /* Attempt to decode the signature */
+ ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out;
+ }
+
+ ret = pkcs7_check_authattrs(ctx->msg);
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out;
+ }
+
+ msg = ctx->msg;
+ ctx->msg = NULL;
+
+out:
+ while (ctx->certs) {
+ struct x509_certificate *cert = ctx->certs;
+ ctx->certs = cert->next;
+ x509_free_certificate(cert);
+ }
+out_no_sig:
+ pkcs7_free_signed_info(ctx->sinfo);
+out_no_sinfo:
+ pkcs7_free_message(ctx->msg);
+out_no_msg:
+ kfree(ctx);
+out_no_ctx:
+ return msg;
+}
+EXPORT_SYMBOL_GPL(pkcs7_parse_message);
+
+/**
+ * pkcs7_get_content_data - Get access to the PKCS#7 content
+ * @pkcs7: The preparsed PKCS#7 message to access
+ * @_data: Place to return a pointer to the data
+ * @_data_len: Place to return the data length
+ * @_headerlen: Size of ASN.1 header not included in _data
+ *
+ * Get access to the data content of the PKCS#7 message. The size of the
+ * header of the ASN.1 object that contains it is also provided and can be used
+ * to adjust *_data and *_data_len to get the entire object.
+ *
+ * Returns -ENODATA if the data object was missing from the message.
+ */
+int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
+ const void **_data, size_t *_data_len,
+ size_t *_headerlen)
+{
+ if (!pkcs7->data)
+ return -ENODATA;
+
+ *_data = pkcs7->data;
+ *_data_len = pkcs7->data_len;
+ if (_headerlen)
+ *_headerlen = pkcs7->data_hdrlen;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
+
+/*
+ * Note an OID when we find one for later processing when we know how
+ * to interpret it.
+ */
+int pkcs7_note_OID(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ ctx->last_oid = look_up_OID(value, vlen);
+ if (ctx->last_oid == OID__NR) {
+ char buffer[50];
+ sprint_oid(value, vlen, buffer, sizeof(buffer));
+ printk("PKCS7: Unknown OID: [%lu] %s\n",
+ (unsigned long)value - ctx->data, buffer);
+ }
+ return 0;
+}
+
+/*
+ * Note the digest algorithm for the signature.
+ */
+int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
+ case OID_md4:
+ ctx->sinfo->sig->hash_algo = "md4";
+ break;
+ case OID_md5:
+ ctx->sinfo->sig->hash_algo = "md5";
+ break;
+ case OID_sha1:
+ ctx->sinfo->sig->hash_algo = "sha1";
+ break;
+ case OID_sha256:
+ ctx->sinfo->sig->hash_algo = "sha256";
+ break;
+ case OID_sha384:
+ ctx->sinfo->sig->hash_algo = "sha384";
+ break;
+ case OID_sha512:
+ ctx->sinfo->sig->hash_algo = "sha512";
+ break;
+ case OID_sha224:
+ ctx->sinfo->sig->hash_algo = "sha224";
+ break;
+ default:
+ printk("Unsupported digest algo: %u\n", ctx->last_oid);
+ return -ENOPKG;
+ }
+ return 0;
+}
+
+/*
+ * Note the public key algorithm for the signature.
+ */
+int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
+ case OID_rsaEncryption:
+ ctx->sinfo->sig->pkey_algo = "rsa";
+ ctx->sinfo->sig->encoding = "pkcs1";
+ break;
+ default:
+ printk("Unsupported pkey algo: %u\n", ctx->last_oid);
+ return -ENOPKG;
+ }
+ return 0;
+}
+
+/*
+ * We only support signed data [RFC2315 sec 9].
+ */
+int pkcs7_check_content_type(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ if (ctx->last_oid != OID_signed_data) {
+ pr_warn("Only support pkcs7_signedData type\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Note the SignedData version
+ */
+int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ unsigned version;
+
+ if (vlen != 1)
+ goto unsupported;
+
+ ctx->msg->version = version = *(const u8 *)value;
+ switch (version) {
+ case 1:
+ /* PKCS#7 SignedData [RFC2315 sec 9.1]
+ * CMS ver 1 SignedData [RFC5652 sec 5.1]
+ */
+ break;
+ case 3:
+ /* CMS ver 3 SignedData [RFC2315 sec 5.1] */
+ break;
+ default:
+ goto unsupported;
+ }
+
+ return 0;
+
+unsupported:
+ pr_warn("Unsupported SignedData version\n");
+ return -EINVAL;
+}
+
+/*
+ * Note the SignerInfo version
+ */
+int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ unsigned version;
+
+ if (vlen != 1)
+ goto unsupported;
+
+ version = *(const u8 *)value;
+ switch (version) {
+ case 1:
+ /* PKCS#7 SignerInfo [RFC2315 sec 9.2]
+ * CMS ver 1 SignerInfo [RFC5652 sec 5.3]
+ */
+ if (ctx->msg->version != 1)
+ goto version_mismatch;
+ ctx->expect_skid = false;
+ break;
+ case 3:
+ /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */
+ if (ctx->msg->version == 1)
+ goto version_mismatch;
+ ctx->expect_skid = true;
+ break;
+ default:
+ goto unsupported;
+ }
+
+ return 0;
+
+unsupported:
+ pr_warn("Unsupported SignerInfo version\n");
+ return -EINVAL;
+version_mismatch:
+ pr_warn("SignedData-SignerInfo version mismatch\n");
+ return -EBADMSG;
+}
+
+/*
+ * Extract a certificate and store it in the context.
+ */
+int pkcs7_extract_cert(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ struct x509_certificate *x509;
+
+ if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
+ pr_debug("Cert began with tag %02x at %lu\n",
+ tag, (unsigned long)ctx - ctx->data);
+ return -EBADMSG;
+ }
+
+ /* We have to correct for the header so that the X.509 parser can start
+ * from the beginning. Note that since X.509 stipulates DER, there
+ * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which
+ * stipulates BER).
+ */
+ value -= hdrlen;
+ vlen += hdrlen;
+
+ if (((u8*)value)[1] == 0x80)
+ vlen += 2; /* Indefinite length - there should be an EOC */
+
+ x509 = x509_cert_parse(value, vlen);
+ if (IS_ERR(x509))
+ return PTR_ERR(x509);
+
+ x509->index = ++ctx->x509_index;
+ pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
+ pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
+
+ *ctx->ppcerts = x509;
+ ctx->ppcerts = &x509->next;
+ return 0;
+}
+
+/*
+ * Save the certificate list
+ */
+int pkcs7_note_certificate_list(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_devel("Got cert list (%02x)\n", tag);
+
+ *ctx->ppcerts = ctx->msg->certs;
+ ctx->msg->certs = ctx->certs;
+ ctx->certs = NULL;
+ ctx->ppcerts = &ctx->certs;
+ return 0;
+}
+
+/*
+ * Note the content type.
+ */
+int pkcs7_note_content(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ if (ctx->last_oid != OID_data &&
+ ctx->last_oid != OID_msIndirectData) {
+ pr_warn("Unsupported data type %d\n", ctx->last_oid);
+ return -EINVAL;
+ }
+
+ ctx->msg->data_type = ctx->last_oid;
+ return 0;
+}
+
+/*
+ * Extract the data from the message and store that and its content type OID in
+ * the context.
+ */
+int pkcs7_note_data(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_debug("Got data\n");
+
+ ctx->msg->data = value;
+ ctx->msg->data_len = vlen;
+ ctx->msg->data_hdrlen = hdrlen;
+ return 0;
+}
+
+/*
+ * Parse authenticated attributes.
+ */
+int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ struct pkcs7_signed_info *sinfo = ctx->sinfo;
+ enum OID content_type;
+
+ pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
+
+ switch (ctx->last_oid) {
+ case OID_contentType:
+ if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
+ goto repeated;
+ content_type = look_up_OID(value, vlen);
+ if (content_type != ctx->msg->data_type) {
+ pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n",
+ ctx->msg->data_type, sinfo->index,
+ content_type);
+ return -EBADMSG;
+ }
+ return 0;
+
+ case OID_signingTime:
+ if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
+ goto repeated;
+ /* Should we check that the signing time is consistent
+ * with the signer's X.509 cert?
+ */
+ return x509_decode_time(&sinfo->signing_time,
+ hdrlen, tag, value, vlen);
+
+ case OID_messageDigest:
+ if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
+ goto repeated;
+ if (tag != ASN1_OTS)
+ return -EBADMSG;
+ sinfo->msgdigest = value;
+ sinfo->msgdigest_len = vlen;
+ return 0;
+
+ case OID_smimeCapabilites:
+ if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
+ goto repeated;
+#ifdef __UBOOT__ /* OID_data is needed for authenticated UEFI variables */
+ if (ctx->msg->data_type != OID_msIndirectData &&
+ ctx->msg->data_type != OID_data) {
+#else
+ if (ctx->msg->data_type != OID_msIndirectData) {
+#endif
+ pr_warn("S/MIME Caps only allowed with Authenticode\n");
+ return -EKEYREJECTED;
+ }
+ return 0;
+
+ /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE
+ * char URLs and cont[1] 8-bit char URLs.
+ *
+ * Microsoft StatementType seems to contain a list of OIDs that
+ * are also used as extendedKeyUsage types in X.509 certs.
+ */
+ case OID_msSpOpusInfo:
+ if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
+ goto repeated;
+ goto authenticode_check;
+ case OID_msStatementType:
+ if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
+ goto repeated;
+ authenticode_check:
+ if (ctx->msg->data_type != OID_msIndirectData) {
+ pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n");
+ return -EKEYREJECTED;
+ }
+ /* I'm not sure how to validate these */
+ return 0;
+ default:
+ return 0;
+ }
+
+repeated:
+ /* We permit max one item per AuthenticatedAttribute and no repeats */
+ pr_warn("Repeated/multivalue AuthAttrs not permitted\n");
+ return -EKEYREJECTED;
+}
+
+/*
+ * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3]
+ */
+int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ struct pkcs7_signed_info *sinfo = ctx->sinfo;
+
+ if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
+ !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) {
+ pr_warn("Missing required AuthAttr\n");
+ return -EBADMSG;
+ }
+
+ if (ctx->msg->data_type != OID_msIndirectData &&
+ test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) {
+ pr_warn("Unexpected Authenticode AuthAttr\n");
+ return -EBADMSG;
+ }
+
+ /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
+ sinfo->authattrs = value - (hdrlen - 1);
+ sinfo->authattrs_len = vlen + (hdrlen - 1);
+ return 0;
+}
+
+/*
+ * Note the issuing certificate serial number
+ */
+int pkcs7_sig_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ ctx->raw_serial = value;
+ ctx->raw_serial_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the issuer's name
+ */
+int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ ctx->raw_issuer = value;
+ ctx->raw_issuer_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the issuing cert's subjectKeyIdentifier
+ */
+int pkcs7_sig_note_skid(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
+
+ ctx->raw_skid = value;
+ ctx->raw_skid_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the signature data
+ */
+int pkcs7_sig_note_signature(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL);
+ if (!ctx->sinfo->sig->s)
+ return -ENOMEM;
+
+ ctx->sinfo->sig->s_size = vlen;
+ return 0;
+}
+
+/*
+ * Note a signature information block
+ */
+int pkcs7_note_signed_info(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ struct pkcs7_signed_info *sinfo = ctx->sinfo;
+ struct asymmetric_key_id *kid;
+
+ if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) {
+ pr_warn("Authenticode requires AuthAttrs\n");
+ return -EBADMSG;
+ }
+
+ /* Generate cert issuer + serial number key ID */
+ if (!ctx->expect_skid) {
+ kid = asymmetric_key_generate_id(ctx->raw_serial,
+ ctx->raw_serial_size,
+ ctx->raw_issuer,
+ ctx->raw_issuer_size);
+ } else {
+ kid = asymmetric_key_generate_id(ctx->raw_skid,
+ ctx->raw_skid_size,
+ "", 0);
+ }
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+
+ pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
+
+ sinfo->sig->auth_ids[0] = kid;
+ sinfo->index = ++ctx->sinfo_index;
+ *ctx->ppsinfo = sinfo;
+ ctx->ppsinfo = &sinfo->next;
+ ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+ if (!ctx->sinfo)
+ return -ENOMEM;
+ ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
+ GFP_KERNEL);
+ if (!ctx->sinfo->sig)
+ return -ENOMEM;
+ return 0;
+}
diff --git a/lib/crypto/pkcs7_parser.h b/lib/crypto/pkcs7_parser.h
new file mode 100644
index 00000000..6565fdc2
--- /dev/null
+++ b/lib/crypto/pkcs7_parser.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* PKCS#7 crypto data parser internal definitions
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/oid_registry.h>
+#include <crypto/pkcs7.h>
+#include "x509_parser.h"
+
+#define kenter(FMT, ...) \
+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+struct pkcs7_signed_info {
+ struct pkcs7_signed_info *next;
+ struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
+ unsigned index;
+ bool unsupported_crypto; /* T if not usable due to missing crypto */
+ bool blacklisted;
+
+ /* Message digest - the digest of the Content Data (or NULL) */
+ const void *msgdigest;
+ unsigned msgdigest_len;
+
+ /* Authenticated Attribute data (or NULL) */
+ unsigned authattrs_len;
+ const void *authattrs;
+ unsigned long aa_set;
+#define sinfo_has_content_type 0
+#define sinfo_has_signing_time 1
+#define sinfo_has_message_digest 2
+#define sinfo_has_smime_caps 3
+#define sinfo_has_ms_opus_info 4
+#define sinfo_has_ms_statement_type 5
+ time64_t signing_time;
+
+ /* Message signature.
+ *
+ * This contains the generated digest of _either_ the Content Data or
+ * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of
+ * the attributes contains the digest of the the Content Data within
+ * it.
+ *
+ * THis also contains the issuing cert serial number and issuer's name
+ * [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3].
+ */
+ struct public_key_signature *sig;
+};
+
+struct pkcs7_message {
+ struct x509_certificate *certs; /* Certificate list */
+ struct x509_certificate *crl; /* Revocation list */
+ struct pkcs7_signed_info *signed_infos;
+ u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */
+ bool have_authattrs; /* T if have authattrs */
+
+ /* Content Data (or NULL) */
+ enum OID data_type; /* Type of Data */
+ size_t data_len; /* Length of Data */
+ size_t data_hdrlen; /* Length of Data ASN.1 header */
+ const void *data; /* Content Data (or 0) */
+};
diff --git a/lib/crypto/public_key.c b/lib/crypto/public_key.c
new file mode 100644
index 00000000..63437747
--- /dev/null
+++ b/lib/crypto/public_key.c
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* In-software asymmetric public-key crypto subtype
+ *
+ * See Documentation/crypto/asymmetric-keys.txt
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#define pr_fmt(fmt) "PKEY: "fmt
+#ifdef __UBOOT__
+#include <linux/compat.h>
+#else
+#include <linux/module.h>
+#include <linux/export.h>
+#endif
+#include <linux/kernel.h>
+#ifndef __UBOOT__
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
+#include <keys/asymmetric-subtype.h>
+#endif
+#include <crypto/public_key.h>
+#ifndef __UBOOT__
+#include <crypto/akcipher.h>
+#endif
+
+MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
+#ifndef __UBOOT__
+/*
+ * Provide a part of a description of the key for /proc/keys.
+ */
+static void public_key_describe(const struct key *asymmetric_key,
+ struct seq_file *m)
+{
+ struct public_key *key = asymmetric_key->payload.data[asym_crypto];
+
+ if (key)
+ seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
+}
+#endif
+
+/*
+ * Destroy a public key algorithm key.
+ */
+void public_key_free(struct public_key *key)
+{
+ if (key) {
+ kfree(key->key);
+ kfree(key->params);
+ kfree(key);
+ }
+}
+EXPORT_SYMBOL_GPL(public_key_free);
+
+#ifdef __UBOOT__
+/*
+ * from <linux>/crypto/asymmetric_keys/signature.c
+ *
+ * Destroy a public key signature.
+ */
+void public_key_signature_free(struct public_key_signature *sig)
+{
+ int i;
+
+ if (sig) {
+ for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++)
+ free(sig->auth_ids[i]);
+ free(sig->s);
+ free(sig->digest);
+ free(sig);
+ }
+}
+EXPORT_SYMBOL_GPL(public_key_signature_free);
+
+#else
+/*
+ * Destroy a public key algorithm key.
+ */
+static void public_key_destroy(void *payload0, void *payload3)
+{
+ public_key_free(payload0);
+ public_key_signature_free(payload3);
+}
+
+/*
+ * Determine the crypto algorithm name.
+ */
+static
+int software_key_determine_akcipher(const char *encoding,
+ const char *hash_algo,
+ const struct public_key *pkey,
+ char alg_name[CRYPTO_MAX_ALG_NAME])
+{
+ int n;
+
+ if (strcmp(encoding, "pkcs1") == 0) {
+ /* The data wangled by the RSA algorithm is typically padded
+ * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
+ * sec 8.2].
+ */
+ if (!hash_algo)
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1pad(%s)",
+ pkey->pkey_algo);
+ else
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1pad(%s,%s)",
+ pkey->pkey_algo, hash_algo);
+ return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
+ }
+
+ if (strcmp(encoding, "raw") == 0) {
+ strcpy(alg_name, pkey->pkey_algo);
+ return 0;
+ }
+
+ return -ENOPKG;
+}
+
+static u8 *pkey_pack_u32(u8 *dst, u32 val)
+{
+ memcpy(dst, &val, sizeof(val));
+ return dst + sizeof(val);
+}
+
+/*
+ * Query information about a key.
+ */
+static int software_key_query(const struct kernel_pkey_params *params,
+ struct kernel_pkey_query *info)
+{
+ struct crypto_akcipher *tfm;
+ struct public_key *pkey = params->key->payload.data[asym_crypto];
+ char alg_name[CRYPTO_MAX_ALG_NAME];
+ u8 *key, *ptr;
+ int ret, len;
+
+ ret = software_key_determine_akcipher(params->encoding,
+ params->hash_algo,
+ pkey, alg_name);
+ if (ret < 0)
+ return ret;
+
+ tfm = crypto_alloc_akcipher(alg_name, 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
+ GFP_KERNEL);
+ if (!key)
+ goto error_free_tfm;
+ memcpy(key, pkey->key, pkey->keylen);
+ ptr = key + pkey->keylen;
+ ptr = pkey_pack_u32(ptr, pkey->algo);
+ ptr = pkey_pack_u32(ptr, pkey->paramlen);
+ memcpy(ptr, pkey->params, pkey->paramlen);
+
+ if (pkey->key_is_private)
+ ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
+ else
+ ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
+ if (ret < 0)
+ goto error_free_key;
+
+ len = crypto_akcipher_maxsize(tfm);
+ info->key_size = len * 8;
+ info->max_data_size = len;
+ info->max_sig_size = len;
+ info->max_enc_size = len;
+ info->max_dec_size = len;
+ info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
+ KEYCTL_SUPPORTS_VERIFY);
+ if (pkey->key_is_private)
+ info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT |
+ KEYCTL_SUPPORTS_SIGN);
+ ret = 0;
+
+error_free_key:
+ kfree(key);
+error_free_tfm:
+ crypto_free_akcipher(tfm);
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+}
+
+/*
+ * Do encryption, decryption and signing ops.
+ */
+static int software_key_eds_op(struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ const struct public_key *pkey = params->key->payload.data[asym_crypto];
+ struct akcipher_request *req;
+ struct crypto_akcipher *tfm;
+ struct crypto_wait cwait;
+ struct scatterlist in_sg, out_sg;
+ char alg_name[CRYPTO_MAX_ALG_NAME];
+ char *key, *ptr;
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ ret = software_key_determine_akcipher(params->encoding,
+ params->hash_algo,
+ pkey, alg_name);
+ if (ret < 0)
+ return ret;
+
+ tfm = crypto_alloc_akcipher(alg_name, 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ req = akcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ goto error_free_tfm;
+
+ key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
+ GFP_KERNEL);
+ if (!key)
+ goto error_free_req;
+
+ memcpy(key, pkey->key, pkey->keylen);
+ ptr = key + pkey->keylen;
+ ptr = pkey_pack_u32(ptr, pkey->algo);
+ ptr = pkey_pack_u32(ptr, pkey->paramlen);
+ memcpy(ptr, pkey->params, pkey->paramlen);
+
+ if (pkey->key_is_private)
+ ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
+ else
+ ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
+ if (ret)
+ goto error_free_key;
+
+ sg_init_one(&in_sg, in, params->in_len);
+ sg_init_one(&out_sg, out, params->out_len);
+ akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
+ params->out_len);
+ crypto_init_wait(&cwait);
+ akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ crypto_req_done, &cwait);
+
+ /* Perform the encryption calculation. */
+ switch (params->op) {
+ case kernel_pkey_encrypt:
+ ret = crypto_akcipher_encrypt(req);
+ break;
+ case kernel_pkey_decrypt:
+ ret = crypto_akcipher_decrypt(req);
+ break;
+ case kernel_pkey_sign:
+ ret = crypto_akcipher_sign(req);
+ break;
+ default:
+ BUG();
+ }
+
+ ret = crypto_wait_req(ret, &cwait);
+ if (ret == 0)
+ ret = req->dst_len;
+
+error_free_key:
+ kfree(key);
+error_free_req:
+ akcipher_request_free(req);
+error_free_tfm:
+ crypto_free_akcipher(tfm);
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+}
+
+/*
+ * Verify a signature using a public key.
+ */
+int public_key_verify_signature(const struct public_key *pkey,
+ const struct public_key_signature *sig)
+{
+ struct crypto_wait cwait;
+ struct crypto_akcipher *tfm;
+ struct akcipher_request *req;
+ struct scatterlist src_sg[2];
+ char alg_name[CRYPTO_MAX_ALG_NAME];
+ char *key, *ptr;
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ BUG_ON(!pkey);
+ BUG_ON(!sig);
+ BUG_ON(!sig->s);
+
+ ret = software_key_determine_akcipher(sig->encoding,
+ sig->hash_algo,
+ pkey, alg_name);
+ if (ret < 0)
+ return ret;
+
+ tfm = crypto_alloc_akcipher(alg_name, 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ ret = -ENOMEM;
+ req = akcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ goto error_free_tfm;
+
+ key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
+ GFP_KERNEL);
+ if (!key)
+ goto error_free_req;
+
+ memcpy(key, pkey->key, pkey->keylen);
+ ptr = key + pkey->keylen;
+ ptr = pkey_pack_u32(ptr, pkey->algo);
+ ptr = pkey_pack_u32(ptr, pkey->paramlen);
+ memcpy(ptr, pkey->params, pkey->paramlen);
+
+ if (pkey->key_is_private)
+ ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
+ else
+ ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
+ if (ret)
+ goto error_free_key;
+
+ sg_init_table(src_sg, 2);
+ sg_set_buf(&src_sg[0], sig->s, sig->s_size);
+ sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
+ akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
+ sig->digest_size);
+ crypto_init_wait(&cwait);
+ akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ crypto_req_done, &cwait);
+ ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
+
+error_free_key:
+ kfree(key);
+error_free_req:
+ akcipher_request_free(req);
+error_free_tfm:
+ crypto_free_akcipher(tfm);
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ if (WARN_ON_ONCE(ret > 0))
+ ret = -EINVAL;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(public_key_verify_signature);
+
+static int public_key_verify_signature_2(const struct key *key,
+ const struct public_key_signature *sig)
+{
+ const struct public_key *pk = key->payload.data[asym_crypto];
+ return public_key_verify_signature(pk, sig);
+}
+
+/*
+ * Public key algorithm asymmetric key subtype
+ */
+struct asymmetric_key_subtype public_key_subtype = {
+ .owner = THIS_MODULE,
+ .name = "public_key",
+ .name_len = sizeof("public_key") - 1,
+ .describe = public_key_describe,
+ .destroy = public_key_destroy,
+ .query = software_key_query,
+ .eds_op = software_key_eds_op,
+ .verify_signature = public_key_verify_signature_2,
+};
+EXPORT_SYMBOL_GPL(public_key_subtype);
+#endif /* !__UBOOT__ */
diff --git a/lib/crypto/rsa_helper.c b/lib/crypto/rsa_helper.c
new file mode 100644
index 00000000..aca627a4
--- /dev/null
+++ b/lib/crypto/rsa_helper.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RSA key extract helper
+ *
+ * Copyright (c) 2015, Intel Corporation
+ * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
+ */
+#ifndef __UBOOT__
+#include <linux/kernel.h>
+#include <linux/export.h>
+#endif
+#include <linux/err.h>
+#ifndef __UBOOT__
+#include <linux/fips.h>
+#endif
+#include <crypto/internal/rsa.h>
+#include "rsapubkey.asn1.h"
+#ifndef __UBOOT__
+#include "rsaprivkey.asn1.h"
+#endif
+
+int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+#ifndef __UBOOT__
+ const u8 *ptr = value;
+ size_t n_sz = vlen;
+#endif
+
+ /* invalid key provided */
+ if (!value || !vlen)
+ return -EINVAL;
+
+#ifndef __UBOOT__
+ if (fips_enabled) {
+ while (n_sz && !*ptr) {
+ ptr++;
+ n_sz--;
+ }
+
+ /* In FIPS mode only allow key size 2K and higher */
+ if (n_sz < 256) {
+ pr_err("RSA: key size not allowed in FIPS mode\n");
+ return -EINVAL;
+ }
+ }
+#endif
+
+ key->n = value;
+ key->n_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !key->n_sz || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->e = value;
+ key->e_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !key->n_sz || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->d = value;
+ key->d_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_p(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->p = value;
+ key->p_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_q(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->q = value;
+ key->q_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_dp(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->dp = value;
+ key->dp_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_dq(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->dq = value;
+ key->dq_sz = vlen;
+
+ return 0;
+}
+
+int rsa_get_qinv(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_key *key = context;
+
+ /* invalid key provided */
+ if (!value || !vlen || vlen > key->n_sz)
+ return -EINVAL;
+
+ key->qinv = value;
+ key->qinv_sz = vlen;
+
+ return 0;
+}
+
+/**
+ * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the
+ * provided struct rsa_key, pointers to the raw key as is,
+ * so that the caller can copy it or MPI parse it, etc.
+ *
+ * @rsa_key: struct rsa_key key representation
+ * @key: key in BER format
+ * @key_len: length of key
+ *
+ * Return: 0 on success or error code in case of error
+ */
+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
+ unsigned int key_len)
+{
+ return asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
+}
+EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
+
+#ifndef __UBOOT__
+/**
+ * rsa_parse_priv_key() - decodes the BER encoded buffer and stores in the
+ * provided struct rsa_key, pointers to the raw key
+ * as is, so that the caller can copy it or MPI parse it,
+ * etc.
+ *
+ * @rsa_key: struct rsa_key key representation
+ * @key: key in BER format
+ * @key_len: length of key
+ *
+ * Return: 0 on success or error code in case of error
+ */
+int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
+ unsigned int key_len)
+{
+ return asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
+}
+EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
+#endif
diff --git a/lib/crypto/rsapubkey.asn1 b/lib/crypto/rsapubkey.asn1
new file mode 100644
index 00000000..725498e4
--- /dev/null
+++ b/lib/crypto/rsapubkey.asn1
@@ -0,0 +1,4 @@
+RsaPubKey ::= SEQUENCE {
+ n INTEGER ({ rsa_get_n }),
+ e INTEGER ({ rsa_get_e })
+}
diff --git a/lib/crypto/x509.asn1 b/lib/crypto/x509.asn1
new file mode 100644
index 00000000..5c9f4e4a
--- /dev/null
+++ b/lib/crypto/x509.asn1
@@ -0,0 +1,60 @@
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }),
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING ({ x509_note_signature })
+ }
+
+TBSCertificate ::= SEQUENCE {
+ version [ 0 ] Version DEFAULT,
+ serialNumber CertificateSerialNumber ({ x509_note_serial }),
+ signature AlgorithmIdentifier ({ x509_note_pkey_algo }),
+ issuer Name ({ x509_note_issuer }),
+ validity Validity,
+ subject Name ({ x509_note_subject }),
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ extensions [ 3 ] Extensions OPTIONAL
+ }
+
+Version ::= INTEGER
+CertificateSerialNumber ::= INTEGER
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ x509_note_OID }),
+ parameters ANY OPTIONAL ({ x509_note_params })
+}
+
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }),
+ attributeValue ANY ({ x509_extract_name_segment })
+ }
+
+Validity ::= SEQUENCE {
+ notBefore Time ({ x509_note_not_before }),
+ notAfter Time ({ x509_note_not_after })
+ }
+
+Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime
+ }
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING ({ x509_extract_key_data })
+ }
+
+UniqueIdentifier ::= BIT STRING
+
+Extensions ::= SEQUENCE OF Extension
+
+Extension ::= SEQUENCE {
+ extnid OBJECT IDENTIFIER ({ x509_note_OID }),
+ critical BOOLEAN DEFAULT,
+ extnValue OCTET STRING ({ x509_process_extension })
+ }
diff --git a/lib/crypto/x509_akid.asn1 b/lib/crypto/x509_akid.asn1
new file mode 100644
index 00000000..1a33231a
--- /dev/null
+++ b/lib/crypto/x509_akid.asn1
@@ -0,0 +1,35 @@
+-- X.509 AuthorityKeyIdentifier
+-- rfc5280 section 4.2.1.1
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL
+ }
+
+KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid })
+
+CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial })
+
+GeneralNames ::= SEQUENCE OF GeneralName
+
+GeneralName ::= CHOICE {
+ otherName [0] ANY,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ANY,
+ directoryName [4] Name ({ x509_akid_note_name }),
+ ediPartyName [5] ANY,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER
+ }
+
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }),
+ attributeValue ANY ({ x509_extract_name_segment })
+ }
diff --git a/lib/crypto/x509_cert_parser.c b/lib/crypto/x509_cert_parser.c
new file mode 100644
index 00000000..e6d2a426
--- /dev/null
+++ b/lib/crypto/x509_cert_parser.c
@@ -0,0 +1,697 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* X.509 certificate parser
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#define pr_fmt(fmt) "X.509: "fmt
+#include <linux/kernel.h>
+#ifndef __UBOOT__
+#include <linux/export.h>
+#include <linux/slab.h>
+#endif
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#ifdef __UBOOT__
+#include <linux/string.h>
+#endif
+#include <crypto/public_key.h>
+#include "x509_parser.h"
+#include "x509.asn1.h"
+#include "x509_akid.asn1.h"
+
+struct x509_parse_context {
+ struct x509_certificate *cert; /* Certificate being constructed */
+ unsigned long data; /* Start of data */
+ const void *cert_start; /* Start of cert content */
+ const void *key; /* Key data */
+ size_t key_size; /* Size of key data */
+ const void *params; /* Key parameters */
+ size_t params_size; /* Size of key parameters */
+ enum OID key_algo; /* Public key algorithm */
+ enum OID last_oid; /* Last OID encountered */
+ enum OID algo_oid; /* Algorithm OID */
+ unsigned char nr_mpi; /* Number of MPIs stored */
+ u8 o_size; /* Size of organizationName (O) */
+ u8 cn_size; /* Size of commonName (CN) */
+ u8 email_size; /* Size of emailAddress */
+ u16 o_offset; /* Offset of organizationName (O) */
+ u16 cn_offset; /* Offset of commonName (CN) */
+ u16 email_offset; /* Offset of emailAddress */
+ unsigned raw_akid_size;
+ const void *raw_akid; /* Raw authorityKeyId in ASN.1 */
+ const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */
+ unsigned akid_raw_issuer_size;
+};
+
+/*
+ * Free an X.509 certificate
+ */
+void x509_free_certificate(struct x509_certificate *cert)
+{
+ if (cert) {
+ public_key_free(cert->pub);
+ public_key_signature_free(cert->sig);
+ kfree(cert->issuer);
+ kfree(cert->subject);
+ kfree(cert->id);
+ kfree(cert->skid);
+ kfree(cert);
+ }
+}
+EXPORT_SYMBOL_GPL(x509_free_certificate);
+
+/*
+ * Parse an X.509 certificate
+ */
+struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
+{
+ struct x509_certificate *cert;
+ struct x509_parse_context *ctx;
+ struct asymmetric_key_id *kid;
+ long ret;
+
+ ret = -ENOMEM;
+ cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL);
+ if (!cert)
+ goto error_no_cert;
+ cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
+ if (!cert->pub)
+ goto error_no_ctx;
+ cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL);
+ if (!cert->sig)
+ goto error_no_ctx;
+ ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
+ if (!ctx)
+ goto error_no_ctx;
+
+ ctx->cert = cert;
+ ctx->data = (unsigned long)data;
+
+ /* Attempt to decode the certificate */
+ ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen);
+ if (ret < 0)
+ goto error_decode;
+
+ /* Decode the AuthorityKeyIdentifier */
+ if (ctx->raw_akid) {
+ pr_devel("AKID: %u %*phN\n",
+ ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid);
+ ret = asn1_ber_decoder(&x509_akid_decoder, ctx,
+ ctx->raw_akid, ctx->raw_akid_size);
+ if (ret < 0) {
+ pr_warn("Couldn't decode AuthKeyIdentifier\n");
+ goto error_decode;
+ }
+ }
+
+ ret = -ENOMEM;
+ cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
+ if (!cert->pub->key)
+ goto error_decode;
+
+ cert->pub->keylen = ctx->key_size;
+
+ cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL);
+ if (!cert->pub->params)
+ goto error_decode;
+
+ cert->pub->paramlen = ctx->params_size;
+ cert->pub->algo = ctx->key_algo;
+
+ /* Grab the signature bits */
+ ret = x509_get_sig_params(cert);
+ if (ret < 0)
+ goto error_decode;
+
+ /* Generate cert issuer + serial number key ID */
+ kid = asymmetric_key_generate_id(cert->raw_serial,
+ cert->raw_serial_size,
+ cert->raw_issuer,
+ cert->raw_issuer_size);
+ if (IS_ERR(kid)) {
+ ret = PTR_ERR(kid);
+ goto error_decode;
+ }
+ cert->id = kid;
+
+#ifndef __UBOOT__
+ /* Detect self-signed certificates */
+ ret = x509_check_for_self_signed(cert);
+ if (ret < 0)
+ goto error_decode;
+#endif
+
+ kfree(ctx);
+ return cert;
+
+error_decode:
+ kfree(ctx);
+error_no_ctx:
+ x509_free_certificate(cert);
+error_no_cert:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(x509_cert_parse);
+
+/*
+ * Note an OID when we find one for later processing when we know how
+ * to interpret it.
+ */
+int x509_note_OID(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ ctx->last_oid = look_up_OID(value, vlen);
+ if (ctx->last_oid == OID__NR) {
+ char buffer[50];
+ sprint_oid(value, vlen, buffer, sizeof(buffer));
+ pr_debug("Unknown OID: [%lu] %s\n",
+ (unsigned long)value - ctx->data, buffer);
+ }
+ return 0;
+}
+
+/*
+ * Save the position of the TBS data so that we can check the signature over it
+ * later.
+ */
+int x509_note_tbs_certificate(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n",
+ hdrlen, tag, (unsigned long)value - ctx->data, vlen);
+
+ ctx->cert->tbs = value - hdrlen;
+ ctx->cert->tbs_size = vlen + hdrlen;
+ return 0;
+}
+
+/*
+ * Record the public key algorithm
+ */
+int x509_note_pkey_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ pr_debug("PubKey Algo: %u\n", ctx->last_oid);
+
+ switch (ctx->last_oid) {
+ case OID_md2WithRSAEncryption:
+ case OID_md3WithRSAEncryption:
+ default:
+ return -ENOPKG; /* Unsupported combination */
+
+ case OID_md4WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "md4";
+ goto rsa_pkcs1;
+
+ case OID_sha1WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha1";
+ goto rsa_pkcs1;
+
+ case OID_sha256WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha256";
+ goto rsa_pkcs1;
+
+ case OID_sha384WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha384";
+ goto rsa_pkcs1;
+
+ case OID_sha512WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha512";
+ goto rsa_pkcs1;
+
+ case OID_sha224WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha224";
+ goto rsa_pkcs1;
+
+ case OID_gost2012Signature256:
+ ctx->cert->sig->hash_algo = "streebog256";
+ goto ecrdsa;
+
+ case OID_gost2012Signature512:
+ ctx->cert->sig->hash_algo = "streebog512";
+ goto ecrdsa;
+ }
+
+rsa_pkcs1:
+ ctx->cert->sig->pkey_algo = "rsa";
+ ctx->cert->sig->encoding = "pkcs1";
+ ctx->algo_oid = ctx->last_oid;
+ return 0;
+ecrdsa:
+ ctx->cert->sig->pkey_algo = "ecrdsa";
+ ctx->cert->sig->encoding = "raw";
+ ctx->algo_oid = ctx->last_oid;
+ return 0;
+}
+
+/*
+ * Note the whereabouts and type of the signature.
+ */
+int x509_note_signature(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen);
+
+ if (ctx->last_oid != ctx->algo_oid) {
+ pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n",
+ ctx->algo_oid, ctx->last_oid);
+ return -EINVAL;
+ }
+
+ if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 ||
+ strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0) {
+ /* Discard the BIT STRING metadata */
+ if (vlen < 1 || *(const u8 *)value != 0)
+ return -EBADMSG;
+
+ value++;
+ vlen--;
+ }
+
+ ctx->cert->raw_sig = value;
+ ctx->cert->raw_sig_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the certificate serial number
+ */
+int x509_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ ctx->cert->raw_serial = value;
+ ctx->cert->raw_serial_size = vlen;
+ return 0;
+}
+
+/*
+ * Note some of the name segments from which we'll fabricate a name.
+ */
+int x509_extract_name_segment(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
+ case OID_commonName:
+ ctx->cn_size = vlen;
+ ctx->cn_offset = (unsigned long)value - ctx->data;
+ break;
+ case OID_organizationName:
+ ctx->o_size = vlen;
+ ctx->o_offset = (unsigned long)value - ctx->data;
+ break;
+ case OID_email_address:
+ ctx->email_size = vlen;
+ ctx->email_offset = (unsigned long)value - ctx->data;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Fabricate and save the issuer and subject names
+ */
+static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen,
+ unsigned char tag,
+ char **_name, size_t vlen)
+{
+ const void *name, *data = (const void *)ctx->data;
+ size_t namesize;
+ char *buffer;
+
+ if (*_name)
+ return -EINVAL;
+
+ /* Empty name string if no material */
+ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) {
+ buffer = kmalloc(1, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ buffer[0] = 0;
+ goto done;
+ }
+
+ if (ctx->cn_size && ctx->o_size) {
+ /* Consider combining O and CN, but use only the CN if it is
+ * prefixed by the O, or a significant portion thereof.
+ */
+ namesize = ctx->cn_size;
+ name = data + ctx->cn_offset;
+ if (ctx->cn_size >= ctx->o_size &&
+ memcmp(data + ctx->cn_offset, data + ctx->o_offset,
+ ctx->o_size) == 0)
+ goto single_component;
+ if (ctx->cn_size >= 7 &&
+ ctx->o_size >= 7 &&
+ memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0)
+ goto single_component;
+
+ buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1,
+ GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ memcpy(buffer,
+ data + ctx->o_offset, ctx->o_size);
+ buffer[ctx->o_size + 0] = ':';
+ buffer[ctx->o_size + 1] = ' ';
+ memcpy(buffer + ctx->o_size + 2,
+ data + ctx->cn_offset, ctx->cn_size);
+ buffer[ctx->o_size + 2 + ctx->cn_size] = 0;
+ goto done;
+
+ } else if (ctx->cn_size) {
+ namesize = ctx->cn_size;
+ name = data + ctx->cn_offset;
+ } else if (ctx->o_size) {
+ namesize = ctx->o_size;
+ name = data + ctx->o_offset;
+ } else {
+ namesize = ctx->email_size;
+ name = data + ctx->email_offset;
+ }
+
+single_component:
+ buffer = kmalloc(namesize + 1, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ memcpy(buffer, name, namesize);
+ buffer[namesize] = 0;
+
+done:
+ *_name = buffer;
+ ctx->cn_size = 0;
+ ctx->o_size = 0;
+ ctx->email_size = 0;
+ return 0;
+}
+
+int x509_note_issuer(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ ctx->cert->raw_issuer = value;
+ ctx->cert->raw_issuer_size = vlen;
+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen);
+}
+
+int x509_note_subject(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ ctx->cert->raw_subject = value;
+ ctx->cert->raw_subject_size = vlen;
+ return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen);
+}
+
+/*
+ * Extract the parameters for the public key
+ */
+int x509_note_params(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ /*
+ * AlgorithmIdentifier is used three times in the x509, we should skip
+ * first and ignore third, using second one which is after subject and
+ * before subjectPublicKey.
+ */
+ if (!ctx->cert->raw_subject || ctx->key)
+ return 0;
+ ctx->params = value - hdrlen;
+ ctx->params_size = vlen + hdrlen;
+ return 0;
+}
+
+/*
+ * Extract the data for the public key algorithm
+ */
+int x509_extract_key_data(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ ctx->key_algo = ctx->last_oid;
+ if (ctx->last_oid == OID_rsaEncryption)
+ ctx->cert->pub->pkey_algo = "rsa";
+ else if (ctx->last_oid == OID_gost2012PKey256 ||
+ ctx->last_oid == OID_gost2012PKey512)
+ ctx->cert->pub->pkey_algo = "ecrdsa";
+ else
+ return -ENOPKG;
+
+ /* Discard the BIT STRING metadata */
+ if (vlen < 1 || *(const u8 *)value != 0)
+ return -EBADMSG;
+ ctx->key = value + 1;
+ ctx->key_size = vlen - 1;
+ return 0;
+}
+
+/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */
+#define SEQ_TAG_KEYID (ASN1_CONT << 6)
+
+/*
+ * Process certificate extensions that are used to qualify the certificate.
+ */
+int x509_process_extension(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
+ const unsigned char *v = value;
+
+ pr_debug("Extension: %u\n", ctx->last_oid);
+
+ if (ctx->last_oid == OID_subjectKeyIdentifier) {
+ /* Get hold of the key fingerprint */
+ if (ctx->cert->skid || vlen < 3)
+ return -EBADMSG;
+ if (v[0] != ASN1_OTS || v[1] != vlen - 2)
+ return -EBADMSG;
+ v += 2;
+ vlen -= 2;
+
+ ctx->cert->raw_skid_size = vlen;
+ ctx->cert->raw_skid = v;
+ kid = asymmetric_key_generate_id(v, vlen, "", 0);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ ctx->cert->skid = kid;
+ pr_debug("subjkeyid %*phN\n", kid->len, kid->data);
+ return 0;
+ }
+
+ if (ctx->last_oid == OID_authorityKeyIdentifier) {
+ /* Get hold of the CA key fingerprint */
+ ctx->raw_akid = v;
+ ctx->raw_akid_size = vlen;
+ return 0;
+ }
+
+ return 0;
+}
+
+/**
+ * x509_decode_time - Decode an X.509 time ASN.1 object
+ * @_t: The time to fill in
+ * @hdrlen: The length of the object header
+ * @tag: The object tag
+ * @value: The object value
+ * @vlen: The size of the object value
+ *
+ * Decode an ASN.1 universal time or generalised time field into a struct the
+ * kernel can handle and check it for validity. The time is decoded thus:
+ *
+ * [RFC5280 §4.1.2.5]
+ * CAs conforming to this profile MUST always encode certificate validity
+ * dates through the year 2049 as UTCTime; certificate validity dates in
+ * 2050 or later MUST be encoded as GeneralizedTime. Conforming
+ * applications MUST be able to process validity dates that are encoded in
+ * either UTCTime or GeneralizedTime.
+ */
+int x509_decode_time(time64_t *_t, size_t hdrlen,
+ unsigned char tag,
+ const unsigned char *value, size_t vlen)
+{
+ static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31 };
+ const unsigned char *p = value;
+ unsigned year, mon, day, hour, min, sec, mon_len;
+
+#define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; })
+#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; })
+
+ if (tag == ASN1_UNITIM) {
+ /* UTCTime: YYMMDDHHMMSSZ */
+ if (vlen != 13)
+ goto unsupported_time;
+ year = DD2bin(p);
+ if (year >= 50)
+ year += 1900;
+ else
+ year += 2000;
+ } else if (tag == ASN1_GENTIM) {
+ /* GenTime: YYYYMMDDHHMMSSZ */
+ if (vlen != 15)
+ goto unsupported_time;
+ year = DD2bin(p) * 100 + DD2bin(p);
+ if (year >= 1950 && year <= 2049)
+ goto invalid_time;
+ } else {
+ goto unsupported_time;
+ }
+
+ mon = DD2bin(p);
+ day = DD2bin(p);
+ hour = DD2bin(p);
+ min = DD2bin(p);
+ sec = DD2bin(p);
+
+ if (*p != 'Z')
+ goto unsupported_time;
+
+ if (year < 1970 ||
+ mon < 1 || mon > 12)
+ goto invalid_time;
+
+ mon_len = month_lengths[mon - 1];
+ if (mon == 2) {
+ if (year % 4 == 0) {
+ mon_len = 29;
+ if (year % 100 == 0) {
+ mon_len = 28;
+ if (year % 400 == 0)
+ mon_len = 29;
+ }
+ }
+ }
+
+ if (day < 1 || day > mon_len ||
+ hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */
+ min > 59 ||
+ sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */
+ goto invalid_time;
+
+ *_t = mktime64(year, mon, day, hour, min, sec);
+ return 0;
+
+unsupported_time:
+ pr_debug("Got unsupported time [tag %02x]: '%*phN'\n",
+ tag, (int)vlen, value);
+ return -EBADMSG;
+invalid_time:
+ pr_debug("Got invalid time [tag %02x]: '%*phN'\n",
+ tag, (int)vlen, value);
+ return -EBADMSG;
+}
+EXPORT_SYMBOL_GPL(x509_decode_time);
+
+int x509_note_not_before(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen);
+}
+
+int x509_note_not_after(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen);
+}
+
+/*
+ * Note a key identifier-based AuthorityKeyIdentifier
+ */
+int x509_akid_note_kid(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
+
+ pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
+
+ if (ctx->cert->sig->auth_ids[1])
+ return 0;
+
+ kid = asymmetric_key_generate_id(value, vlen, "", 0);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->sig->auth_ids[1] = kid;
+ return 0;
+}
+
+/*
+ * Note a directoryName in an AuthorityKeyIdentifier
+ */
+int x509_akid_note_name(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ pr_debug("AKID: name: %*phN\n", (int)vlen, value);
+
+ ctx->akid_raw_issuer = value;
+ ctx->akid_raw_issuer_size = vlen;
+ return 0;
+}
+
+/*
+ * Note a serial number in an AuthorityKeyIdentifier
+ */
+int x509_akid_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
+
+ pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
+
+ if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0])
+ return 0;
+
+ kid = asymmetric_key_generate_id(value,
+ vlen,
+ ctx->akid_raw_issuer,
+ ctx->akid_raw_issuer_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->sig->auth_ids[0] = kid;
+ return 0;
+}
diff --git a/lib/crypto/x509_parser.h b/lib/crypto/x509_parser.h
new file mode 100644
index 00000000..c233f136
--- /dev/null
+++ b/lib/crypto/x509_parser.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* X.509 certificate parser internal definitions
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/time.h>
+#include <crypto/public_key.h>
+#include <keys/asymmetric-type.h>
+
+struct x509_certificate {
+ struct x509_certificate *next;
+ struct x509_certificate *signer; /* Certificate that signed this one */
+ struct public_key *pub; /* Public key details */
+ struct public_key_signature *sig; /* Signature parameters */
+ char *issuer; /* Name of certificate issuer */
+ char *subject; /* Name of certificate subject */
+ struct asymmetric_key_id *id; /* Issuer + Serial number */
+ struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */
+ time64_t valid_from;
+ time64_t valid_to;
+ const void *tbs; /* Signed data */
+ unsigned tbs_size; /* Size of signed data */
+ unsigned raw_sig_size; /* Size of sigature */
+ const void *raw_sig; /* Signature data */
+ const void *raw_serial; /* Raw serial number in ASN.1 */
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer; /* Raw issuer name in ASN.1 */
+ const void *raw_subject; /* Raw subject name in ASN.1 */
+ unsigned raw_subject_size;
+ unsigned raw_skid_size;
+ const void *raw_skid; /* Raw subjectKeyId in ASN.1 */
+ unsigned index;
+ bool seen; /* Infinite recursion prevention */
+ bool verified;
+ bool self_signed; /* T if self-signed (check unsupported_sig too) */
+ bool unsupported_key; /* T if key uses unsupported crypto */
+ bool unsupported_sig; /* T if signature uses unsupported crypto */
+ bool blacklisted;
+};
+
+/*
+ * x509_cert_parser.c
+ */
+extern void x509_free_certificate(struct x509_certificate *cert);
+extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
+extern int x509_decode_time(time64_t *_t, size_t hdrlen,
+ unsigned char tag,
+ const unsigned char *value, size_t vlen);
+
+/*
+ * x509_public_key.c
+ */
+extern int x509_get_sig_params(struct x509_certificate *cert);
+extern int x509_check_for_self_signed(struct x509_certificate *cert);
diff --git a/lib/crypto/x509_public_key.c b/lib/crypto/x509_public_key.c
new file mode 100644
index 00000000..04bdb672
--- /dev/null
+++ b/lib/crypto/x509_public_key.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Instantiate a public key crypto key from an X.509 Certificate
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#define pr_fmt(fmt) "X.509: "fmt
+#ifdef __UBOOT__
+#include <common.h>
+#include <linux/compat.h>
+#include <linux/errno.h>
+#else
+#include <linux/module.h>
+#endif
+#include <linux/kernel.h>
+#ifndef __UBOOT__
+#include <linux/slab.h>
+#include <keys/asymmetric-subtype.h>
+#include <keys/asymmetric-parser.h>
+#include <keys/system_keyring.h>
+#include <crypto/hash.h>
+#include "asymmetric_keys.h"
+#endif
+#include "x509_parser.h"
+
+/*
+ * Set up the signature parameters in an X.509 certificate. This involves
+ * digesting the signed data and extracting the signature.
+ */
+int x509_get_sig_params(struct x509_certificate *cert)
+{
+ struct public_key_signature *sig = cert->sig;
+#ifndef __UBOOT__
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ size_t desc_size;
+#endif
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (!cert->pub->pkey_algo)
+ cert->unsupported_key = true;
+
+ if (!sig->pkey_algo)
+ cert->unsupported_sig = true;
+
+ /* We check the hash if we can - even if we can't then verify it */
+ if (!sig->hash_algo) {
+ cert->unsupported_sig = true;
+ return 0;
+ }
+
+ sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
+ if (!sig->s)
+ return -ENOMEM;
+
+ sig->s_size = cert->raw_sig_size;
+
+#ifdef __UBOOT__
+ /*
+ * Note:
+ * This part (filling sig->digest) should be implemented if
+ * x509_check_for_self_signed() is enabled x509_cert_parse().
+ * Currently, this check won't affect UEFI secure boot.
+ */
+ ret = 0;
+#else
+ /* Allocate the hashing algorithm we're going to need and find out how
+ * big the hash operational data will be.
+ */
+ tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
+ if (IS_ERR(tfm)) {
+ if (PTR_ERR(tfm) == -ENOENT) {
+ cert->unsupported_sig = true;
+ return 0;
+ }
+ return PTR_ERR(tfm);
+ }
+
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ sig->digest_size = crypto_shash_digestsize(tfm);
+
+ ret = -ENOMEM;
+ sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
+ if (!sig->digest)
+ goto error;
+
+ desc = kzalloc(desc_size, GFP_KERNEL);
+ if (!desc)
+ goto error;
+
+ desc->tfm = tfm;
+
+ ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
+ if (ret < 0)
+ goto error_2;
+
+ ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs");
+ if (ret == -EKEYREJECTED) {
+ pr_err("Cert %*phN is blacklisted\n",
+ sig->digest_size, sig->digest);
+ cert->blacklisted = true;
+ ret = 0;
+ }
+
+error_2:
+ kfree(desc);
+error:
+ crypto_free_shash(tfm);
+#endif /* __UBOOT__ */
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+}
+
+#ifndef __UBOOT__
+/*
+ * Check for self-signedness in an X.509 cert and if found, check the signature
+ * immediately if we can.
+ */
+int x509_check_for_self_signed(struct x509_certificate *cert)
+{
+ int ret = 0;
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (cert->raw_subject_size != cert->raw_issuer_size ||
+ memcmp(cert->raw_subject, cert->raw_issuer,
+ cert->raw_issuer_size) != 0)
+ goto not_self_signed;
+
+ if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
+ /* If the AKID is present it may have one or two parts. If
+ * both are supplied, both must match.
+ */
+ bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
+ bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
+
+ if (!a && !b)
+ goto not_self_signed;
+
+ ret = -EKEYREJECTED;
+ if (((a && !b) || (b && !a)) &&
+ cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
+ goto out;
+ }
+
+ ret = -EKEYREJECTED;
+ if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
+ goto out;
+
+ ret = public_key_verify_signature(cert->pub, cert->sig);
+ if (ret < 0) {
+ if (ret == -ENOPKG) {
+ cert->unsupported_sig = true;
+ ret = 0;
+ }
+ goto out;
+ }
+
+ pr_devel("Cert Self-signature verified");
+ cert->self_signed = true;
+
+out:
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
+
+not_self_signed:
+ pr_devel("<==%s() = 0 [not]\n", __func__);
+ return 0;
+}
+
+/*
+ * Attempt to parse a data blob for a key as an X509 certificate.
+ */
+static int x509_key_preparse(struct key_preparsed_payload *prep)
+{
+ struct asymmetric_key_ids *kids;
+ struct x509_certificate *cert;
+ const char *q;
+ size_t srlen, sulen;
+ char *desc = NULL, *p;
+ int ret;
+
+ cert = x509_cert_parse(prep->data, prep->datalen);
+ if (IS_ERR(cert))
+ return PTR_ERR(cert);
+
+ pr_devel("Cert Issuer: %s\n", cert->issuer);
+ pr_devel("Cert Subject: %s\n", cert->subject);
+
+ if (cert->unsupported_key) {
+ ret = -ENOPKG;
+ goto error_free_cert;
+ }
+
+ pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
+ pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
+
+ cert->pub->id_type = "X509";
+
+ if (cert->unsupported_sig) {
+ public_key_signature_free(cert->sig);
+ cert->sig = NULL;
+ } else {
+ pr_devel("Cert Signature: %s + %s\n",
+ cert->sig->pkey_algo, cert->sig->hash_algo);
+ }
+
+ /* Don't permit addition of blacklisted keys */
+ ret = -EKEYREJECTED;
+ if (cert->blacklisted)
+ goto error_free_cert;
+
+ /* Propose a description */
+ sulen = strlen(cert->subject);
+ if (cert->raw_skid) {
+ srlen = cert->raw_skid_size;
+ q = cert->raw_skid;
+ } else {
+ srlen = cert->raw_serial_size;
+ q = cert->raw_serial;
+ }
+
+ ret = -ENOMEM;
+ desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
+ if (!desc)
+ goto error_free_cert;
+ p = memcpy(desc, cert->subject, sulen);
+ p += sulen;
+ *p++ = ':';
+ *p++ = ' ';
+ p = bin2hex(p, q, srlen);
+ *p = 0;
+
+ kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
+ if (!kids)
+ goto error_free_desc;
+ kids->id[0] = cert->id;
+ kids->id[1] = cert->skid;
+
+ /* We're pinning the module by being linked against it */
+ __module_get(public_key_subtype.owner);
+ prep->payload.data[asym_subtype] = &public_key_subtype;
+ prep->payload.data[asym_key_ids] = kids;
+ prep->payload.data[asym_crypto] = cert->pub;
+ prep->payload.data[asym_auth] = cert->sig;
+ prep->description = desc;
+ prep->quotalen = 100;
+
+ /* We've finished with the certificate */
+ cert->pub = NULL;
+ cert->id = NULL;
+ cert->skid = NULL;
+ cert->sig = NULL;
+ desc = NULL;
+ ret = 0;
+
+error_free_desc:
+ kfree(desc);
+error_free_cert:
+ x509_free_certificate(cert);
+ return ret;
+}
+
+static struct asymmetric_key_parser x509_key_parser = {
+ .owner = THIS_MODULE,
+ .name = "x509",
+ .parse = x509_key_preparse,
+};
+
+/*
+ * Module stuff
+ */
+static int __init x509_key_init(void)
+{
+ return register_asymmetric_key_parser(&x509_key_parser);
+}
+
+static void __exit x509_key_exit(void)
+{
+ unregister_asymmetric_key_parser(&x509_key_parser);
+}
+
+module_init(x509_key_init);
+module_exit(x509_key_exit);
+#endif /* !__UBOOT__ */
+
+MODULE_DESCRIPTION("X.509 certificate parser");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/lib/ctype.c b/lib/ctype.c
new file mode 100644
index 00000000..1892e202
--- /dev/null
+++ b/lib/ctype.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * linux/lib/ctype.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/ctype.h>
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
diff --git a/lib/date.c b/lib/date.c
new file mode 100644
index 00000000..0456de78
--- /dev/null
+++ b/lib/date.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <rtc.h>
+#include <linux/time.h>
+
+#if defined(CONFIG_LIB_DATE) || defined(CONFIG_TIMESTAMP)
+
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
+#define leapyear(year) ((year) % 4 == 0)
+#define days_in_year(a) (leapyear(a) ? 366 : 365)
+#define days_in_month(a) (month_days[(a) - 1])
+
+static int month_offset[] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+int rtc_calc_weekday(struct rtc_time *tm)
+{
+ int leaps_to_date;
+ int last_year;
+ int day;
+
+ if (tm->tm_year < 1753)
+ return -1;
+ last_year = tm->tm_year - 1;
+
+ /* Number of leap corrections to apply up to end of last year */
+ leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400;
+
+ /*
+ * This year is a leap year if it is divisible by 4 except when it is
+ * divisible by 100 unless it is divisible by 400
+ *
+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is.
+ */
+ if (tm->tm_year % 4 == 0 &&
+ ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
+ tm->tm_mon > 2) {
+ /* We are past Feb. 29 in a leap year */
+ day = 1;
+ } else {
+ day = 0;
+ }
+
+ day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] +
+ tm->tm_mday;
+ tm->tm_wday = day % 7;
+
+ return 0;
+}
+
+/*
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year / 100 + year / 400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines where long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+unsigned long rtc_mktime(const struct rtc_time *tm)
+{
+ int mon = tm->tm_mon;
+ int year = tm->tm_year;
+ int days, hours;
+
+ mon -= 2;
+ if (0 >= (int)mon) { /* 1..12 -> 11, 12, 1..10 */
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
+ }
+
+ days = (unsigned long)(year / 4 - year / 100 + year / 400 +
+ 367 * mon / 12 + tm->tm_mday) +
+ year * 365 - 719499;
+ hours = days * 24 + tm->tm_hour;
+ return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec;
+}
+
+#endif /* CONFIG_LIB_DATE || CONFIG_TIMESTAMP */
+
+#ifdef CONFIG_LIB_DATE
+/* for compatibility with linux code */
+time64_t mktime64(const unsigned int year, const unsigned int mon,
+ const unsigned int day, const unsigned int hour,
+ const unsigned int min, const unsigned int sec)
+{
+ struct rtc_time time;
+
+ time.tm_year = year;
+ time.tm_mon = mon;
+ time.tm_mday = day;
+ time.tm_hour = hour;
+ time.tm_min = min;
+ time.tm_sec = sec;
+
+ return (time64_t)rtc_mktime((const struct rtc_time *)&time);
+}
+#endif
diff --git a/lib/dhry/Kconfig b/lib/dhry/Kconfig
new file mode 100644
index 00000000..641b8064
--- /dev/null
+++ b/lib/dhry/Kconfig
@@ -0,0 +1,7 @@
+config CMD_DHRYSTONE
+ bool "Support the 'dhry' command to run the dhrystone benchmark"
+ help
+ Dhrystone is an old benchmark in the public domain that gives a
+ rough idea of CPU performance. This enables a 'dhry' command
+ which runs this benchmark within U-Boot and reports the performance.
+ The number of 'Dhrystone MIPS' is also reported.
diff --git a/lib/dhry/Makefile b/lib/dhry/Makefile
new file mode 100644
index 00000000..10dd9eba
--- /dev/null
+++ b/lib/dhry/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2015 Google, Inc
+
+obj-y += cmd_dhry.o dhry_1.o dhry_2.o
diff --git a/lib/dhry/cmd_dhry.c b/lib/dhry/cmd_dhry.c
new file mode 100644
index 00000000..29504833
--- /dev/null
+++ b/lib/dhry/cmd_dhry.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <div64.h>
+#include "dhry.h"
+
+static int do_dhry(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong start, duration, vax_mips;
+ u64 dhry_per_sec;
+ int iterations = 1000000;
+
+ if (argc > 1)
+ iterations = simple_strtoul(argv[1], NULL, 10);
+
+ start = get_timer(0);
+ dhry(iterations);
+ duration = get_timer(start);
+ dhry_per_sec = lldiv(iterations * 1000ULL, duration);
+ vax_mips = lldiv(dhry_per_sec, 1757);
+ printf("%d iterations in %lu ms: %lu/s, %lu DMIPS\n", iterations,
+ duration, (ulong)dhry_per_sec, vax_mips);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ dhry, 2, 1, do_dhry,
+ "[iterations] - run dhrystone benchmark",
+ "\n - run the Dhrystone 2.1 benchmark, a rough measure of CPU speed\n"
+);
diff --git a/lib/dhry/dhry.h b/lib/dhry/dhry.h
new file mode 100644
index 00000000..892c9ed7
--- /dev/null
+++ b/lib/dhry/dhry.h
@@ -0,0 +1,441 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * Dhrystone is widely available in the public domain. A GPL license is
+ * chosen for U-Boot.
+ */
+
+/*****************************************************************************
+ * The BYTE UNIX Benchmarks - Release 3
+ * Module: dhry.h SID: 3.4 5/15/91 19:30:21
+ *
+ *****************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * Ben Smith, Rick Grehan or Tom Yager
+ * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
+ *
+ *****************************************************************************
+ * Modification Log:
+ * addapted from:
+ *
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry.h (part 1 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Author: Reinhold P. Weicker
+ * Siemens AG, AUT E 51
+ * Postfach 3220
+ * 8520 Erlangen
+ * Germany (West)
+ * Phone: [+49]-9131-7-20330
+ * (8-17 Central European Time)
+ * Usenet: ..!mcvax!unido!estevax!weicker
+ *
+ * Original Version (in Ada) published in
+ * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
+ * pp. 1013 - 1030, together with the statistics
+ * on which the distribution of statements etc. is based.
+ *
+ * In this C version, the following C library functions are used:
+ * - strcpy, strcmp (inside the measurement loop)
+ * - printf, scanf (outside the measurement loop)
+ * In addition, Berkeley UNIX system calls "times ()" or "time ()"
+ * are used for execution time measurement. For measurements
+ * on other systems, these calls have to be changed.
+ *
+ * Collection of Results:
+ * Reinhold Weicker (address see above) and
+ *
+ * Rick Richardson
+ * PC Research. Inc.
+ * 94 Apple Orchard Drive
+ * Tinton Falls, NJ 07724
+ * Phone: (201) 834-1378 (9-17 EST)
+ * Usenet: ...!seismo!uunet!pcrat!rick
+ *
+ * Please send results to Rick Richardson and/or Reinhold Weicker.
+ * Complete information should be given on hardware and software used.
+ * Hardware information includes: Machine type, CPU, type and size
+ * of caches; for microprocessors: clock frequency, memory speed
+ * (number of wait states).
+ * Software information includes: Compiler (and runtime library)
+ * manufacturer and version, compilation switches, OS version.
+ * The Operating System version may give an indication about the
+ * compiler; Dhrystone itself performs no OS calls in the measurement loop.
+ *
+ * The complete output generated by the program should be mailed
+ * such that at least some checks for correctness can be made.
+ *
+ ***************************************************************************
+ *
+ * History: This version C/2.1 has been made for two reasons:
+ *
+ * 1) There is an obvious need for a common C version of
+ * Dhrystone, since C is at present the most popular system
+ * programming language for the class of processors
+ * (microcomputers, minicomputers) where Dhrystone is used most.
+ * There should be, as far as possible, only one C version of
+ * Dhrystone such that results can be compared without
+ * restrictions. In the past, the C versions distributed
+ * by Rick Richardson (Version 1.1) and by Reinhold Weicker
+ * had small (though not significant) differences.
+ *
+ * 2) As far as it is possible without changes to the Dhrystone
+ * statistics, optimizing compilers should be prevented from
+ * removing significant statements.
+ *
+ * This C version has been developed in cooperation with
+ * Rick Richardson (Tinton Falls, NJ), it incorporates many
+ * ideas from the "Version 1.1" distributed previously by
+ * him over the UNIX network Usenet.
+ * I also thank Chaim Benedelac (National Semiconductor),
+ * David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
+ * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
+ * for their help with comments on earlier versions of the
+ * benchmark.
+ *
+ * Changes: In the initialization part, this version follows mostly
+ * Rick Richardson's version distributed via Usenet, not the
+ * version distributed earlier via floppy disk by Reinhold Weicker.
+ * As a concession to older compilers, names have been made
+ * unique within the first 8 characters.
+ * Inside the measurement loop, this version follows the
+ * version previously distributed by Reinhold Weicker.
+ *
+ * At several places in the benchmark, code has been added,
+ * but within the measurement loop only in branches that
+ * are not executed. The intention is that optimizing compilers
+ * should be prevented from moving code out of the measurement
+ * loop, or from removing code altogether. Since the statements
+ * that are executed within the measurement loop have NOT been
+ * changed, the numbers defining the "Dhrystone distribution"
+ * (distribution of statements, operand types and locality)
+ * still hold. Except for sophisticated optimizing compilers,
+ * execution times for this version should be the same as
+ * for previous versions.
+ *
+ * Since it has proven difficult to subtract the time for the
+ * measurement loop overhead in a correct way, the loop check
+ * has been made a part of the benchmark. This does have
+ * an impact - though a very minor one - on the distribution
+ * statistics which have been updated for this version.
+ *
+ * All changes within the measurement loop are described
+ * and discussed in the companion paper "Rationale for
+ * Dhrystone version 2".
+ *
+ * Because of the self-imposed limitation that the order and
+ * distribution of the executed statements should not be
+ * changed, there are still cases where optimizing compilers
+ * may not generate code for some statements. To a certain
+ * degree, this is unavoidable for small synthetic benchmarks.
+ * Users of the benchmark are advised to check code listings
+ * whether code is generated for all statements of Dhrystone.
+ *
+ * Version 2.1 is identical to version 2.0 distributed via
+ * the UNIX network Usenet in March 1988 except that it corrects
+ * some minor deficiencies that were found by users of version 2.0.
+ * The only change within the measurement loop is that a
+ * non-executed "else" part was added to the "if" statement in
+ * Func_3, and a non-executed "else" part removed from Proc_3.
+ *
+ ***************************************************************************
+ *
+ * Defines: The following "Defines" are possible:
+ * -DREG=register (default: Not defined)
+ * As an approximation to what an average C programmer
+ * might do, the "register" storage class is applied
+ * (if enabled by -DREG=register)
+ * - for local variables, if they are used (dynamically)
+ * five or more times
+ * - for parameters if they are used (dynamically)
+ * six or more times
+ * Note that an optimal "register" strategy is
+ * compiler-dependent, and that "register" declarations
+ * do not necessarily lead to faster execution.
+ * -DNOSTRUCTASSIGN (default: Not defined)
+ * Define if the C compiler does not support
+ * assignment of structures.
+ * -DNOENUMS (default: Not defined)
+ * Define if the C compiler does not support
+ * enumeration types.
+ * -DTIMES (default)
+ * -DTIME
+ * The "times" function of UNIX (returning process times)
+ * or the "time" function (returning wallclock time)
+ * is used for measurement.
+ * For single user machines, "time ()" is adequate. For
+ * multi-user machines where you cannot get single-user
+ * access, use the "times ()" function. If you have
+ * neither, use a stopwatch in the dead of night.
+ * "printf"s are provided marking the points "Start Timer"
+ * and "Stop Timer". DO NOT use the UNIX "time(1)"
+ * command, as this will measure the total time to
+ * run this program, which will (erroneously) include
+ * the time to allocate storage (malloc) and to perform
+ * the initialization.
+ * -DHZ=nnn
+ * In Berkeley UNIX, the function "times" returns process
+ * time in 1/HZ seconds, with HZ = 60 for most systems.
+ * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
+ * A VALUE.
+ *
+ ***************************************************************************
+ *
+ * Compilation model and measurement (IMPORTANT):
+ *
+ * This C version of Dhrystone consists of three files:
+ * - dhry.h (this file, containing global definitions and comments)
+ * - dhry_1.c (containing the code corresponding to Ada package Pack_1)
+ * - dhry_2.c (containing the code corresponding to Ada package Pack_2)
+ *
+ * The following "ground rules" apply for measurements:
+ * - Separate compilation
+ * - No procedure merging
+ * - Otherwise, compiler optimizations are allowed but should be indicated
+ * - Default results are those without register declarations
+ * See the companion paper "Rationale for Dhrystone Version 2" for a more
+ * detailed discussion of these ground rules.
+ *
+ * For 16-Bit processors (e.g. 80186, 80286), times for all compilation
+ * models ("small", "medium", "large" etc.) should be given if possible,
+ * together with a definition of these models for the compiler system used.
+ *
+ **************************************************************************
+ *
+ * Dhrystone (C version) statistics:
+ *
+ * [Comment from the first distribution, updated for version 2.
+ * Note that because of language differences, the numbers are slightly
+ * different from the Ada version.]
+ *
+ * The following program contains statements of a high level programming
+ * language (here: C) in a distribution considered representative:
+ *
+ * assignments 52 (51.0 %)
+ * control statements 33 (32.4 %)
+ * procedure, function calls 17 (16.7 %)
+ *
+ * 103 statements are dynamically executed. The program is balanced with
+ * respect to the three aspects:
+ *
+ * - statement type
+ * - operand type
+ * - operand locality
+ * operand global, local, parameter, or constant.
+ *
+ * The combination of these three aspects is balanced only approximately.
+ *
+ * 1. Statement Type:
+ * ----------------- number
+ *
+ * V1 = V2 9
+ * (incl. V1 = F(..)
+ * V = Constant 12
+ * Assignment, 7
+ * with array element
+ * Assignment, 6
+ * with record component
+ * --
+ * 34 34
+ *
+ * X = Y +|-|"&&"|"|" Z 5
+ * X = Y +|-|"==" Constant 6
+ * X = X +|- 1 3
+ * X = Y *|/ Z 2
+ * X = Expression, 1
+ * two operators
+ * X = Expression, 1
+ * three operators
+ * --
+ * 18 18
+ *
+ * if .... 14
+ * with "else" 7
+ * without "else" 7
+ * executed 3
+ * not executed 4
+ * for ... 7 | counted every time
+ * while ... 4 | the loop condition
+ * do ... while 1 | is evaluated
+ * switch ... 1
+ * break 1
+ * declaration with 1
+ * initialization
+ * --
+ * 34 34
+ *
+ * P (...) procedure call 11
+ * user procedure 10
+ * library procedure 1
+ * X = F (...)
+ * function call 6
+ * user function 5
+ * library function 1
+ * --
+ * 17 17
+ * ---
+ * 103
+ *
+ * The average number of parameters in procedure or function calls
+ * is 1.82 (not counting the function values as implicit parameters).
+ *
+ *
+ * 2. Operators
+ * ------------
+ * number approximate
+ * percentage
+ *
+ * Arithmetic 32 50.8
+ *
+ * + 21 33.3
+ * - 7 11.1
+ * * 3 4.8
+ * / (int div) 1 1.6
+ *
+ * Comparison 27 42.8
+ *
+ * == 9 14.3
+ * /= 4 6.3
+ * > 1 1.6
+ * < 3 4.8
+ * >= 1 1.6
+ * <= 9 14.3
+ *
+ * Logic 4 6.3
+ *
+ * && (AND-THEN) 1 1.6
+ * | (OR) 1 1.6
+ * ! (NOT) 2 3.2
+ *
+ * -- -----
+ * 63 100.1
+ *
+ *
+ * 3. Operand Type (counted once per operand reference):
+ * ---------------
+ * number approximate
+ * percentage
+ *
+ * Integer 175 72.3 %
+ * Character 45 18.6 %
+ * Pointer 12 5.0 %
+ * String30 6 2.5 %
+ * Array 2 0.8 %
+ * Record 2 0.8 %
+ * --- -------
+ * 242 100.0 %
+ *
+ * When there is an access path leading to the final operand (e.g. a record
+ * component), only the final data type on the access path is counted.
+ *
+ *
+ * 4. Operand Locality:
+ * -------------------
+ * number approximate
+ * percentage
+ *
+ * local variable 114 47.1 %
+ * global variable 22 9.1 %
+ * parameter 45 18.6 %
+ * value 23 9.5 %
+ * reference 22 9.1 %
+ * function result 6 2.5 %
+ * constant 55 22.7 %
+ * --- -------
+ * 242 100.0 %
+ *
+ *
+ * The program does not compute anything meaningful, but it is syntactically
+ * and semantically correct. All variables have a value assigned to them
+ * before they are used as a source operand.
+ *
+ * There has been no explicit effort to account for the effects of a
+ * cache, or to balance the use of long or short displacements for code or
+ * data.
+ *
+ ***************************************************************************
+ */
+
+
+/* Compiler and system dependent definitions: */
+
+#ifndef TIME
+#define TIMES
+#endif
+ /* Use times(2) time function unless */
+ /* explicitly defined otherwise */
+
+#define Mic_secs_Per_Second 1000000.0
+ /* Berkeley UNIX C returns process times in seconds/HZ */
+
+#ifdef NOSTRUCTASSIGN
+#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
+#else
+#define structassign(d, s) d = s
+#endif
+
+#ifdef NOENUM
+#define Ident_1 0
+#define Ident_2 1
+#define Ident_3 2
+#define Ident_4 3
+#define Ident_5 4
+ typedef int Enumeration;
+#else
+ typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
+ Enumeration;
+#endif
+ /* for boolean and enumeration types in Ada, Pascal */
+
+/* General definitions: */
+
+#define Null 0
+ /* Value of a Null pointer */
+#define true 1
+#define false 0
+
+typedef int One_Thirty;
+typedef int One_Fifty;
+typedef char Capital_Letter;
+typedef int Boolean;
+typedef char Str_30 [31];
+typedef int Arr_1_Dim [50];
+typedef int Arr_2_Dim [50] [50];
+
+typedef struct record
+ {
+ struct record *Ptr_Comp;
+ Enumeration Discr;
+ union {
+ struct {
+ Enumeration Enum_Comp;
+ int Int_Comp;
+ char Str_Comp [31];
+ } var_1;
+ struct {
+ Enumeration E_Comp_2;
+ char Str_2_Comp [31];
+ } var_2;
+ struct {
+ char Ch_1_Comp;
+ char Ch_2_Comp;
+ } var_3;
+ } variant;
+ } Rec_Type, *Rec_Pointer;
+
+
+/*
+ * dhry() - run dhrystone for a given number of iterations
+ *
+ * @iterations: Number of iterations to run
+ */
+void dhry(int iterations);
diff --git a/lib/dhry/dhry_1.c b/lib/dhry/dhry_1.c
new file mode 100644
index 00000000..dcc224fb
--- /dev/null
+++ b/lib/dhry/dhry_1.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * Dhrystone is widely available in the public domain. A GPL license is
+ * chosen for U-Boot.
+ */
+
+/*****************************************************************************
+ * The BYTE UNIX Benchmarks - Release 3
+ * Module: dhry_1.c SID: 3.4 5/15/91 19:30:21
+ *
+ *****************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * Ben Smith, Rick Grehan or Tom Yager
+ * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
+ *
+ *****************************************************************************
+ *
+ * *** WARNING **** With BYTE's modifications applied, results obtained with
+ * ******* this version of the Dhrystone program may not be applicable
+ * to other versions.
+ *
+ * Modification Log:
+ * 10/22/97 - code cleanup to remove ANSI C compiler warnings
+ * Andy Kahn <kahn@zk3.dec.com>
+ *
+ * Adapted from:
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_1.c (part 2 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ***************************************************************************/
+char SCCSid[] = "@(#) @(#)dhry_1.c:3.4 -- 5/15/91 19:30:21";
+
+#include <common.h>
+#include <malloc.h>
+
+#include "dhry.h"
+
+unsigned long Run_Index;
+
+void report(void)
+{
+ printf("%ld loops\n", Run_Index);
+}
+
+/* Global Variables: */
+
+Rec_Pointer Ptr_Glob,
+ Next_Ptr_Glob;
+int Int_Glob;
+Boolean Bool_Glob;
+char Ch_1_Glob,
+ Ch_2_Glob;
+int Arr_1_Glob [50];
+int Arr_2_Glob [50] [50];
+
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
+ /* forward declaration necessary since Enumeration may not simply be int */
+
+#ifndef REG
+ Boolean Reg = false;
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#else
+ Boolean Reg = true;
+#endif
+
+/* variables for time measurement: */
+
+#ifdef TIMES
+#define Too_Small_Time 120
+ /* Measurements should last at least about 2 seconds */
+#endif
+#ifdef TIME
+extern long time();
+ /* see library function "time" */
+#define Too_Small_Time 2
+ /* Measurements should last at least 2 seconds */
+#endif
+
+long Begin_Time,
+ End_Time,
+ User_Time;
+
+/* end of variables for time measurement */
+
+void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
+void Proc_2 (One_Fifty *Int_Par_Ref);
+void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
+void Proc_4 (void);
+void Proc_5 (void);
+
+
+extern Boolean Func_2(Str_30, Str_30);
+extern void Proc_6(Enumeration, Enumeration *);
+extern void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
+extern void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);
+
+void dhry(int Number_Of_Runs)
+ /* main program, corresponds to procedures */
+ /* Main and Proc_0 in the Ada version */
+{
+ One_Fifty Int_1_Loc;
+ REG One_Fifty Int_2_Loc;
+ One_Fifty Int_3_Loc;
+ REG char Ch_Index;
+ Enumeration Enum_Loc;
+ Str_30 Str_1_Loc;
+ Str_30 Str_2_Loc;
+
+ /* Initializations */
+
+ Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
+ Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
+
+ Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
+ Ptr_Glob->Discr = Ident_1;
+ Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
+ Ptr_Glob->variant.var_1.Int_Comp = 40;
+ strcpy (Ptr_Glob->variant.var_1.Str_Comp,
+ "DHRYSTONE PROGRAM, SOME STRING");
+ strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
+
+ Arr_2_Glob [8][7] = 10;
+ /* Was missing in published program. Without this statement, */
+ /* Arr_2_Glob [8][7] would have an undefined value. */
+ /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
+ /* overflow may occur for this array element. */
+
+#ifdef PRATTLE
+ printf ("\n");
+ printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
+ printf ("\n");
+ if (Reg)
+ {
+ printf ("Program compiled with 'register' attribute\n");
+ printf ("\n");
+ }
+ else
+ {
+ printf ("Program compiled without 'register' attribute\n");
+ printf ("\n");
+ }
+ printf ("Please give the number of runs through the benchmark: ");
+ {
+ int n;
+ scanf ("%d", &n);
+ Number_Of_Runs = n;
+ }
+ printf ("\n");
+
+ printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
+#endif /* PRATTLE */
+
+ Run_Index = 0;
+
+ /***************/
+ /* Start timer */
+ /***************/
+
+#ifdef SELF_TIMED
+#ifdef TIMES
+ times (&time_info);
+ Begin_Time = (long) time_info.tms_utime;
+#endif
+#ifdef TIME
+ Begin_Time = time ( (long *) 0);
+#endif
+#endif /* SELF_TIMED */
+
+ for (Run_Index = 1; Run_Index < Number_Of_Runs; ++Run_Index)
+ {
+
+ Proc_5();
+ Proc_4();
+ /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
+ Int_1_Loc = 2;
+ Int_2_Loc = 3;
+ strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+ Enum_Loc = Ident_2;
+ Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
+ /* Bool_Glob == 1 */
+ while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
+ {
+ Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+ /* Int_3_Loc == 7 */
+ Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
+ /* Int_3_Loc == 7 */
+ Int_1_Loc += 1;
+ } /* while */
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
+ /* Int_Glob == 5 */
+ Proc_1 (Ptr_Glob);
+ for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+ /* loop body executed twice */
+ {
+ if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+ /* then, not executed */
+ {
+ Proc_6 (Ident_1, &Enum_Loc);
+ strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
+ Int_2_Loc = Run_Index;
+ Int_Glob = Run_Index;
+ }
+ }
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Int_2_Loc = Int_2_Loc * Int_1_Loc;
+ Int_1_Loc = Int_2_Loc / Int_3_Loc;
+ Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+ /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
+ Proc_2 (&Int_1_Loc);
+ /* Int_1_Loc == 5 */
+
+ } /* loop "for Run_Index" */
+
+ /**************/
+ /* Stop timer */
+ /**************/
+#ifdef SELF_TIMED
+#ifdef TIMES
+ times (&time_info);
+ End_Time = (long) time_info.tms_utime;
+#endif
+#ifdef TIME
+ End_Time = time ( (long *) 0);
+#endif
+#endif /* SELF_TIMED */
+
+ /* BYTE version never executes this stuff */
+#ifdef SELF_TIMED
+ printf ("Execution ends\n");
+ printf ("\n");
+ printf ("Final values of the variables used in the benchmark:\n");
+ printf ("\n");
+ printf ("Int_Glob: %d\n", Int_Glob);
+ printf (" should be: %d\n", 5);
+ printf ("Bool_Glob: %d\n", Bool_Glob);
+ printf (" should be: %d\n", 1);
+ printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
+ printf (" should be: %c\n", 'A');
+ printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
+ printf (" should be: %c\n", 'B');
+ printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
+ printf (" should be: %d\n", 7);
+ printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
+ printf (" should be: Number_Of_Runs + 10\n");
+ printf ("Ptr_Glob->\n");
+ printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
+ printf (" should be: (implementation-dependent)\n");
+ printf (" Discr: %d\n", Ptr_Glob->Discr);
+ printf (" should be: %d\n", 0);
+ printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
+ printf (" should be: %d\n", 2);
+ printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
+ printf (" should be: %d\n", 17);
+ printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
+ printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ printf ("Next_Ptr_Glob->\n");
+ printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
+ printf (" should be: (implementation-dependent), same as above\n");
+ printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
+ printf (" should be: %d\n", 0);
+ printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
+ printf (" should be: %d\n", 1);
+ printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
+ printf (" should be: %d\n", 18);
+ printf (" Str_Comp: %s\n",
+ Next_Ptr_Glob->variant.var_1.Str_Comp);
+ printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ printf ("Int_1_Loc: %d\n", Int_1_Loc);
+ printf (" should be: %d\n", 5);
+ printf ("Int_2_Loc: %d\n", Int_2_Loc);
+ printf (" should be: %d\n", 13);
+ printf ("Int_3_Loc: %d\n", Int_3_Loc);
+ printf (" should be: %d\n", 7);
+ printf ("Enum_Loc: %d\n", Enum_Loc);
+ printf (" should be: %d\n", 1);
+ printf ("Str_1_Loc: %s\n", Str_1_Loc);
+ printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
+ printf ("Str_2_Loc: %s\n", Str_2_Loc);
+ printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
+ printf ("\n");
+
+ User_Time = End_Time - Begin_Time;
+
+ if (User_Time < Too_Small_Time)
+ {
+ printf ("Measured time too small to obtain meaningful results\n");
+ printf ("Please increase number of runs\n");
+ printf ("\n");
+ }
+ else
+ {
+#ifdef TIME
+ Microseconds = (float) User_Time * Mic_secs_Per_Second
+ / (float) Number_Of_Runs;
+ Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
+#else
+ Microseconds = (float) User_Time * Mic_secs_Per_Second
+ / ((float) HZ * ((float) Number_Of_Runs));
+ Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
+ / (float) User_Time;
+#endif
+ printf ("Microseconds for one run through Dhrystone: ");
+ printf ("%6.1f \n", Microseconds);
+ printf ("Dhrystones per Second: ");
+ printf ("%6.1f \n", Dhrystones_Per_Second);
+ printf ("\n");
+ }
+#endif /* SELF_TIMED */
+}
+
+
+void Proc_1 (REG Rec_Pointer Ptr_Val_Par)
+ /* executed once */
+{
+ REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
+ /* == Ptr_Glob_Next */
+ /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
+ /* corresponds to "rename" in Ada, "with" in Pascal */
+
+ structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
+ Ptr_Val_Par->variant.var_1.Int_Comp = 5;
+ Next_Record->variant.var_1.Int_Comp
+ = Ptr_Val_Par->variant.var_1.Int_Comp;
+ Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
+ Proc_3 (&Next_Record->Ptr_Comp);
+ /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
+ == Ptr_Glob->Ptr_Comp */
+ if (Next_Record->Discr == Ident_1)
+ /* then, executed */
+ {
+ Next_Record->variant.var_1.Int_Comp = 6;
+ Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
+ &Next_Record->variant.var_1.Enum_Comp);
+ Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
+ Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
+ &Next_Record->variant.var_1.Int_Comp);
+ }
+ else /* not executed */
+ structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
+} /* Proc_1 */
+
+
+void Proc_2 (One_Fifty *Int_Par_Ref)
+ /* executed once */
+ /* *Int_Par_Ref == 1, becomes 4 */
+{
+ One_Fifty Int_Loc;
+ Enumeration Enum_Loc;
+
+ Enum_Loc = 0;
+
+ Int_Loc = *Int_Par_Ref + 10;
+ do /* executed once */
+ if (Ch_1_Glob == 'A')
+ /* then, executed */
+ {
+ Int_Loc -= 1;
+ *Int_Par_Ref = Int_Loc - Int_Glob;
+ Enum_Loc = Ident_1;
+ } /* if */
+ while (Enum_Loc != Ident_1); /* true */
+} /* Proc_2 */
+
+
+void Proc_3 (Rec_Pointer *Ptr_Ref_Par)
+ /* executed once */
+ /* Ptr_Ref_Par becomes Ptr_Glob */
+{
+ if (Ptr_Glob != Null)
+ /* then, executed */
+ *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
+ Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
+} /* Proc_3 */
+
+
+void Proc_4 (void) /* without parameters */
+ /* executed once */
+{
+ Boolean Bool_Loc;
+
+ Bool_Loc = Ch_1_Glob == 'A';
+ Bool_Glob = Bool_Loc | Bool_Glob;
+ Ch_2_Glob = 'B';
+} /* Proc_4 */
+
+void Proc_5 (void) /* without parameters */
+/*******/
+ /* executed once */
+{
+ Ch_1_Glob = 'A';
+ Bool_Glob = false;
+} /* Proc_5 */
+
+
+ /* Procedure for the assignment of structures, */
+ /* if the C compiler doesn't support this feature */
+#ifdef NOSTRUCTASSIGN
+memcpy (d, s, l)
+register char *d;
+register char *s;
+register int l;
+{
+ while (l--) *d++ = *s++;
+}
+#endif
diff --git a/lib/dhry/dhry_2.c b/lib/dhry/dhry_2.c
new file mode 100644
index 00000000..1ba87967
--- /dev/null
+++ b/lib/dhry/dhry_2.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * Dhrystone is widely available in the public domain. A GPL license is
+ * chosen for U-Boot.
+ */
+
+/*****************************************************************************
+ * The BYTE UNIX Benchmarks - Release 3
+ * Module: dhry_2.c SID: 3.4 5/15/91 19:30:22
+ *
+ *****************************************************************************
+ * Bug reports, patches, comments, suggestions should be sent to:
+ *
+ * Ben Smith, Rick Grehan or Tom Yager
+ * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
+ *
+ *****************************************************************************
+ * Modification Log:
+ * 10/22/97 - code cleanup to remove ANSI C compiler warnings
+ * Andy Kahn <kahn@zk3.dec.com>
+ *
+ * Adapted from:
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * **** WARNING **** See warning in n.dhry_1.c
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_2.c (part 3 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ****************************************************************************/
+/* SCCSid is defined in dhry_1.c */
+
+#include <common.h>
+#include "dhry.h"
+
+#ifndef REG
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#endif
+
+extern int Int_Glob;
+extern char Ch_1_Glob;
+
+void Proc_6(Enumeration, Enumeration *);
+void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
+void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);
+Enumeration Func_1(Capital_Letter, Capital_Letter);
+Boolean Func_2(Str_30, Str_30);
+Boolean Func_3(Enumeration);
+
+void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
+ /* executed once */
+ /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
+{
+ *Enum_Ref_Par = Enum_Val_Par;
+ if (! Func_3 (Enum_Val_Par))
+ /* then, not executed */
+ *Enum_Ref_Par = Ident_4;
+ switch (Enum_Val_Par)
+ {
+ case Ident_1:
+ *Enum_Ref_Par = Ident_1;
+ break;
+ case Ident_2:
+ if (Int_Glob > 100)
+ /* then */
+ *Enum_Ref_Par = Ident_1;
+ else *Enum_Ref_Par = Ident_4;
+ break;
+ case Ident_3: /* executed */
+ *Enum_Ref_Par = Ident_2;
+ break;
+ case Ident_4: break;
+ case Ident_5:
+ *Enum_Ref_Par = Ident_3;
+ break;
+ } /* switch */
+} /* Proc_6 */
+
+void Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
+One_Fifty Int_1_Par_Val;
+One_Fifty Int_2_Par_Val;
+One_Fifty *Int_Par_Ref;
+/**********************************************/
+ /* executed three times */
+ /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
+ /* Int_Par_Ref becomes 7 */
+ /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
+ /* Int_Par_Ref becomes 17 */
+ /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
+ /* Int_Par_Ref becomes 18 */
+{
+ One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 2;
+ *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
+} /* Proc_7 */
+
+
+void Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
+/*********************************************************************/
+ /* executed once */
+ /* Int_Par_Val_1 == 3 */
+ /* Int_Par_Val_2 == 7 */
+Arr_1_Dim Arr_1_Par_Ref;
+Arr_2_Dim Arr_2_Par_Ref;
+int Int_1_Par_Val;
+int Int_2_Par_Val;
+{
+ REG One_Fifty Int_Index;
+ REG One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 5;
+ Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
+ Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
+ Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
+ for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
+ Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
+ Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
+ Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
+ Int_Glob = 5;
+} /* Proc_8 */
+
+
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
+/*************************************************/
+ /* executed three times */
+ /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
+ /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
+ /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
+{
+ Capital_Letter Ch_1_Loc;
+ Capital_Letter Ch_2_Loc;
+
+ Ch_1_Loc = Ch_1_Par_Val;
+ Ch_2_Loc = Ch_1_Loc;
+ if (Ch_2_Loc != Ch_2_Par_Val)
+ /* then, executed */
+ return (Ident_1);
+ else /* not executed */
+ {
+ Ch_1_Glob = Ch_1_Loc;
+ return (Ident_2);
+ }
+} /* Func_1 */
+
+
+
+Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
+/*************************************************/
+ /* executed once */
+ /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
+ /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
+
+Str_30 Str_1_Par_Ref;
+Str_30 Str_2_Par_Ref;
+{
+ REG One_Thirty Int_Loc;
+ Capital_Letter Ch_Loc;
+
+ Ch_Loc = 'A';
+ Int_Loc = 2;
+ while (Int_Loc <= 2) /* loop body executed once */
+ if (Func_1 (Str_1_Par_Ref[Int_Loc],
+ Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
+ /* then, executed */
+ {
+ Ch_Loc = 'A';
+ Int_Loc += 1;
+ } /* if, while */
+ if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
+ /* then, not executed */
+ Int_Loc = 7;
+ if (Ch_Loc == 'R')
+ /* then, not executed */
+ return (true);
+ else /* executed */
+ {
+ if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
+ /* then, not executed */
+ {
+ Int_Loc += 7;
+ Int_Glob = Int_Loc;
+ return (true);
+ }
+ else /* executed */
+ return (false);
+ } /* if Ch_Loc */
+} /* Func_2 */
+
+
+Boolean Func_3 (Enum_Par_Val)
+/***************************/
+ /* executed once */
+ /* Enum_Par_Val == Ident_3 */
+Enumeration Enum_Par_Val;
+{
+ Enumeration Enum_Loc;
+
+ Enum_Loc = Enum_Par_Val;
+ if (Enum_Loc == Ident_3)
+ /* then, executed */
+ return (true);
+ else /* not executed */
+ return (false);
+} /* Func_3 */
diff --git a/lib/display_options.c b/lib/display_options.c
new file mode 100644
index 00000000..ec16d75e
--- /dev/null
+++ b/lib/display_options.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <console.h>
+#include <div64.h>
+#include <version.h>
+#include <linux/ctype.h>
+#include <asm/io.h>
+
+char *display_options_get_banner_priv(bool newlines, const char *build_tag,
+ char *buf, int size)
+{
+ int len;
+
+ len = snprintf(buf, size, "%s%s", newlines ? "\n\n" : "",
+ version_string);
+ if (build_tag && len < size)
+ len += snprintf(buf + len, size - len, ", Build: %s",
+ build_tag);
+ if (len > size - 3)
+ len = size - 3;
+ if (len < 0)
+ len = 0;
+ snprintf(buf + len, size - len, "\n\n");
+
+ return buf;
+}
+
+#ifndef BUILD_TAG
+#define BUILD_TAG NULL
+#endif
+
+char *display_options_get_banner(bool newlines, char *buf, int size)
+{
+ return display_options_get_banner_priv(newlines, BUILD_TAG, buf, size);
+}
+
+int display_options(void)
+{
+ char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
+
+ display_options_get_banner(true, buf, sizeof(buf));
+ printf("%s", buf);
+
+ return 0;
+}
+
+void print_freq(uint64_t freq, const char *s)
+{
+ unsigned long m = 0;
+ uint32_t f;
+ static const char names[] = {'G', 'M', 'K'};
+ unsigned long d = 1e9;
+ char c = 0;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(names); i++, d /= 1000) {
+ if (freq >= d) {
+ c = names[i];
+ break;
+ }
+ }
+
+ if (!c) {
+ printf("%llu Hz%s", freq, s);
+ return;
+ }
+
+ f = do_div(freq, d);
+
+ /* If there's a remainder, show the first few digits */
+ if (f) {
+ m = f;
+ while (m > 1000)
+ m /= 10;
+ while (m && !(m % 10))
+ m /= 10;
+ if (m >= 100)
+ m = (m / 10) + (m % 100 >= 50);
+ }
+
+ printf("%lu", (unsigned long) freq);
+ if (m)
+ printf(".%ld", m);
+ printf(" %cHz%s", c, s);
+}
+
+void print_size(uint64_t size, const char *s)
+{
+ unsigned long m = 0, n;
+ uint64_t f;
+ static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'};
+ unsigned long d = 10 * ARRAY_SIZE(names);
+ char c = 0;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) {
+ if (size >> d) {
+ c = names[i];
+ break;
+ }
+ }
+
+ if (!c) {
+ printf("%llu Bytes%s", size, s);
+ return;
+ }
+
+ n = size >> d;
+ f = size & ((1ULL << d) - 1);
+
+ /* If there's a remainder, deal with it */
+ if (f) {
+ m = (10ULL * f + (1ULL << (d - 1))) >> d;
+
+ if (m >= 10) {
+ m -= 10;
+ n += 1;
+ }
+ }
+
+ printf ("%lu", n);
+ if (m) {
+ printf (".%ld", m);
+ }
+ printf (" %ciB%s", c, s);
+}
+
+#define MAX_LINE_LENGTH_BYTES (64)
+#define DEFAULT_LINE_LENGTH_BYTES (16)
+int print_buffer(ulong addr, const void *data, uint width, uint count,
+ uint linelen)
+{
+ /* linebuf as a union causes proper alignment */
+ union linebuf {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+ uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1];
+#endif
+ uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1];
+ uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1];
+ uint8_t uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1];
+ } lb;
+ int i;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+ uint64_t __maybe_unused x;
+#else
+ uint32_t __maybe_unused x;
+#endif
+
+ if (linelen*width > MAX_LINE_LENGTH_BYTES)
+ linelen = MAX_LINE_LENGTH_BYTES / width;
+ if (linelen < 1)
+ linelen = DEFAULT_LINE_LENGTH_BYTES / width;
+
+ while (count) {
+ uint thislinelen = linelen;
+ printf("%08lx:", addr);
+
+ /* check for overflow condition */
+ if (count < thislinelen)
+ thislinelen = count;
+
+ /* Copy from memory into linebuf and print hex values */
+ for (i = 0; i < thislinelen; i++) {
+ if (width == 4)
+ x = lb.ui[i] = *(volatile uint32_t *)data;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+ else if (width == 8)
+ x = lb.uq[i] = *(volatile uint64_t *)data;
+#endif
+ else if (width == 2)
+ x = lb.us[i] = *(volatile uint16_t *)data;
+ else
+ x = lb.uc[i] = *(volatile uint8_t *)data;
+#if defined(CONFIG_SPL_BUILD)
+ printf(" %x", (uint)x);
+#elif defined(CONFIG_SYS_SUPPORT_64BIT_DATA)
+ printf(" %0*llx", width * 2, (long long)x);
+#else
+ printf(" %0*x", width * 2, x);
+#endif
+ data += width;
+ }
+
+ while (thislinelen < linelen) {
+ /* fill line with whitespace for nice ASCII print */
+ for (i=0; i<width*2+1; i++)
+ puts(" ");
+ linelen--;
+ }
+
+ /* Print data in ASCII characters */
+ for (i = 0; i < thislinelen * width; i++) {
+ if (!isprint(lb.uc[i]) || lb.uc[i] >= 0x80)
+ lb.uc[i] = '.';
+ }
+ lb.uc[i] = '\0';
+ printf(" %s\n", lb.uc);
+
+ /* update references */
+ addr += thislinelen * width;
+ count -= thislinelen;
+
+#ifndef CONFIG_SPL_BUILD
+ if (ctrlc())
+ return -1;
+#endif
+ }
+
+ return 0;
+}
diff --git a/lib/div64.c b/lib/div64.c
new file mode 100644
index 00000000..62933c92
--- /dev/null
+++ b/lib/div64.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ *
+ * Based on former do_div() implementation from asm-parisc/div64.h:
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *
+ * Generic C version of 64bit/32bit division and modulo, with
+ * 64bit result and 32bit remainder.
+ *
+ * The fast case for (n>>32 == 0) is handled inline by do_div().
+ *
+ * Code generated for this function might be very inefficient
+ * for some CPUs. __div64_32() can be overridden by linking arch-specific
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
+ * or by defining a preprocessor macro in arch/include/asm/div64.h.
+ */
+
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
+#ifndef __div64_32
+/*
+ * Don't instrument this function as it may be called from tracing code, since
+ * it needs to read the timer and this often requires calling do_div(), which
+ * calls this function.
+ */
+uint32_t __attribute__((weak, no_instrument_function)) __div64_32(u64 *n,
+ u32 base)
+{
+ u64 rem = *n;
+ u64 b = base;
+ u64 res, d = 1;
+ u32 high = rem >> 32;
+
+ /* Reduce the thing a bit first */
+ res = 0;
+ if (high >= base) {
+ high /= base;
+ res = (u64)high << 32;
+ rem -= (u64)(high * base) << 32;
+ }
+
+ while ((int64_t)b > 0 && b < rem) {
+ b = b+b;
+ d = d+d;
+ }
+
+ do {
+ if (rem >= b) {
+ rem -= b;
+ res += d;
+ }
+ b >>= 1;
+ d >>= 1;
+ } while (d);
+
+ *n = res;
+ return rem;
+}
+EXPORT_SYMBOL(__div64_32);
+#endif
+
+#ifndef div_s64_rem
+s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+ u64 quotient;
+
+ if (dividend < 0) {
+ quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
+ *remainder = -*remainder;
+ if (divisor > 0)
+ quotient = -quotient;
+ } else {
+ quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
+ if (divisor < 0)
+ quotient = -quotient;
+ }
+ return quotient;
+}
+EXPORT_SYMBOL(div_s64_rem);
+#endif
+
+/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ * @remainder: 64bit remainder
+ *
+ * This implementation is a comparable to algorithm used by div64_u64.
+ * But this operation, which includes math for calculating the remainder,
+ * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
+ * systems.
+ */
+#ifndef div64_u64_rem
+u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+ u32 high = divisor >> 32;
+ u64 quot;
+
+ if (high == 0) {
+ u32 rem32;
+ quot = div_u64_rem(dividend, divisor, &rem32);
+ *remainder = rem32;
+ } else {
+ int n = 1 + fls(high);
+ quot = div_u64(dividend >> n, divisor >> n);
+
+ if (quot != 0)
+ quot--;
+
+ *remainder = dividend - quot * divisor;
+ if (*remainder >= divisor) {
+ quot++;
+ *remainder -= divisor;
+ }
+ }
+
+ return quot;
+}
+EXPORT_SYMBOL(div64_u64_rem);
+#endif
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'. The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
+ */
+#ifndef div64_u64
+u64 div64_u64(u64 dividend, u64 divisor)
+{
+ u32 high = divisor >> 32;
+ u64 quot;
+
+ if (high == 0) {
+ quot = div_u64(dividend, divisor);
+ } else {
+ int n = 1 + fls(high);
+ quot = div_u64(dividend >> n, divisor >> n);
+
+ if (quot != 0)
+ quot--;
+ if ((dividend - quot * divisor) >= divisor)
+ quot++;
+ }
+
+ return quot;
+}
+EXPORT_SYMBOL(div64_u64);
+#endif
+
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+ s64 quot, t;
+
+ quot = div64_u64(abs(dividend), abs(divisor));
+ t = (dividend ^ divisor) >> 63;
+
+ return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#endif
+
+#endif /* BITS_PER_LONG == 32 */
+
+/*
+ * Iterative div/mod for use when dividend is not expected to be much
+ * bigger than divisor.
+ */
+u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+ return __iter_div_u64_rem(dividend, divisor, remainder);
+}
+EXPORT_SYMBOL(iter_div_u64_rem);
diff --git a/lib/efi/Kconfig b/lib/efi/Kconfig
new file mode 100644
index 00000000..919e314a
--- /dev/null
+++ b/lib/efi/Kconfig
@@ -0,0 +1,54 @@
+config EFI
+ bool "Support running U-Boot from EFI"
+ depends on X86
+ help
+ U-Boot can be started from EFI on certain platforms. This allows
+ EFI to perform most of the system init and then jump to U-Boot for
+ final system boot. Another option is to run U-Boot as an EFI
+ application, with U-Boot using EFI's drivers instead of its own.
+
+choice
+ prompt "Select EFI mode to use"
+ depends on X86 && EFI
+
+config EFI_APP
+ bool "Support running as an EFI application"
+ help
+ Build U-Boot as an application which can be started from EFI. This
+ is useful for examining a platform in the early stages of porting
+ U-Boot to it. It allows only very basic functionality, such as a
+ command prompt and memory and I/O functions. Use 'reset' to return
+ to EFI.
+
+config EFI_STUB
+ bool "Support running as an EFI payload"
+
+endchoice
+
+config EFI_RAM_SIZE
+ hex "Amount of EFI RAM for U-Boot"
+ depends on EFI_APP
+ default 0x2000000
+ help
+ Set the amount of EFI RAM which is claimed by U-Boot for its own
+ use. U-Boot allocates this from EFI on start-up (along with a few
+ other smaller amounts) and it can never be increased after that.
+ It is used as the RAM size in with U-Boot.
+
+choice
+ prompt "EFI 32/64-bit selection"
+ depends on EFI_STUB
+ help
+ EFI does not support mixing 32-bit and 64-bit modes. This is a
+ significant problem because it means that you must build a stub with
+ the correct type for EFI to load it correctly. If you are using
+ 32-bit EFI, select 32-bit here, else select 64-bit. Failure to do
+ this may produce no error message - it just won't start!
+
+config EFI_STUB_32BIT
+ bool "Produce a stub for running with 32-bit EFI"
+
+config EFI_STUB_64BIT
+ bool "Produce a stub for running with 64-bit EFI"
+
+endchoice
diff --git a/lib/efi/Makefile b/lib/efi/Makefile
new file mode 100644
index 00000000..a790d2d5
--- /dev/null
+++ b/lib/efi/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2015 Google, Inc
+
+obj-$(CONFIG_EFI_APP) += efi_app.o efi.o
+obj-$(CONFIG_EFI_STUB) += efi_info.o
+
+CFLAGS_REMOVE_efi_stub.o := -mregparm=3 \
+ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
+CFLAGS_efi_stub.o := -fpic -fshort-wchar \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
+CFLAGS_REMOVE_efi.o := -mregparm=3 \
+ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32)
+CFLAGS_efi.o := -fpic -fshort-wchar \
+ $(if $(CONFIG_EFI_STUB_64BIT),-m64)
+
+extra-$(CONFIG_EFI_STUB) += efi_stub.o efi.o
diff --git a/lib/efi/efi.c b/lib/efi/efi.c
new file mode 100644
index 00000000..7cba57b1
--- /dev/null
+++ b/lib/efi/efi.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * EFI information obtained here:
+ * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
+ *
+ * Common EFI functions
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <efi.h>
+#include <efi_api.h>
+
+/*
+ * Unfortunately we cannot access any code outside what is built especially
+ * for the stub. lib/string.c is already being built for the U-Boot payload
+ * so it uses the wrong compiler flags. Add our own memset() here.
+ */
+static void efi_memset(void *ptr, int ch, int size)
+{
+ char *dest = ptr;
+
+ while (size-- > 0)
+ *dest++ = ch;
+}
+
+/*
+ * Since the EFI stub cannot access most of the U-Boot code, add our own
+ * simple console output functions here. The EFI app will not use these since
+ * it can use the normal console.
+ */
+void efi_putc(struct efi_priv *priv, const char ch)
+{
+ struct efi_simple_text_output_protocol *con = priv->sys_table->con_out;
+ uint16_t ucode[2];
+
+ ucode[0] = ch;
+ ucode[1] = '\0';
+ con->output_string(con, ucode);
+}
+
+void efi_puts(struct efi_priv *priv, const char *str)
+{
+ while (*str)
+ efi_putc(priv, *str++);
+}
+
+int efi_init(struct efi_priv *priv, const char *banner, efi_handle_t image,
+ struct efi_system_table *sys_table)
+{
+ efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+ struct efi_boot_services *boot = sys_table->boottime;
+ struct efi_loaded_image *loaded_image;
+ int ret;
+
+ efi_memset(priv, '\0', sizeof(*priv));
+ priv->sys_table = sys_table;
+ priv->boot = sys_table->boottime;
+ priv->parent_image = image;
+ priv->run = sys_table->runtime;
+
+ efi_puts(priv, "U-Boot EFI ");
+ efi_puts(priv, banner);
+ efi_putc(priv, ' ');
+
+ ret = boot->open_protocol(priv->parent_image, &loaded_image_guid,
+ (void **)&loaded_image, priv->parent_image,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret) {
+ efi_puts(priv, "Failed to get loaded image protocol\n");
+ return ret;
+ }
+ priv->image_data_type = loaded_image->image_data_type;
+
+ return 0;
+}
+
+void *efi_malloc(struct efi_priv *priv, int size, efi_status_t *retp)
+{
+ struct efi_boot_services *boot = priv->boot;
+ void *buf = NULL;
+
+ *retp = boot->allocate_pool(priv->image_data_type, size, &buf);
+
+ return buf;
+}
+
+void efi_free(struct efi_priv *priv, void *ptr)
+{
+ struct efi_boot_services *boot = priv->boot;
+
+ boot->free_pool(ptr);
+}
diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c
new file mode 100644
index 00000000..0047998e
--- /dev/null
+++ b/lib/efi/efi_app.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * EFI information obtained here:
+ * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
+ *
+ * This file implements U-Boot running as an EFI application.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <sysreset.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct efi_priv *global_priv;
+
+struct efi_system_table *efi_get_sys_table(void)
+{
+ return global_priv->sys_table;
+}
+
+unsigned long efi_get_ram_base(void)
+{
+ return global_priv->ram_base;
+}
+
+static efi_status_t setup_memory(struct efi_priv *priv)
+{
+ struct efi_boot_services *boot = priv->boot;
+ efi_physical_addr_t addr;
+ efi_status_t ret;
+ int pages;
+
+ /*
+ * Use global_data_ptr instead of gd since it is an assignment. There
+ * are very few assignments to global_data in U-Boot and this makes
+ * it easier to find them.
+ */
+ global_data_ptr = efi_malloc(priv, sizeof(struct global_data), &ret);
+ if (!global_data_ptr)
+ return ret;
+ memset(gd, '\0', sizeof(*gd));
+
+ gd->malloc_base = (ulong)efi_malloc(priv, CONFIG_VAL(SYS_MALLOC_F_LEN),
+ &ret);
+ if (!gd->malloc_base)
+ return ret;
+ pages = CONFIG_EFI_RAM_SIZE >> 12;
+
+ /*
+ * Don't allocate any memory above 4GB. U-Boot is a 32-bit application
+ * so we want it to load below 4GB.
+ */
+ addr = 1ULL << 32;
+ ret = boot->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+ priv->image_data_type, pages, &addr);
+ if (ret) {
+ printf("(using pool %lx) ", ret);
+ priv->ram_base = (ulong)efi_malloc(priv, CONFIG_EFI_RAM_SIZE,
+ &ret);
+ if (!priv->ram_base)
+ return ret;
+ priv->use_pool_for_malloc = true;
+ } else {
+ priv->ram_base = addr;
+ }
+ gd->ram_size = pages << 12;
+
+ return 0;
+}
+
+static void free_memory(struct efi_priv *priv)
+{
+ struct efi_boot_services *boot = priv->boot;
+
+ if (priv->use_pool_for_malloc)
+ efi_free(priv, (void *)priv->ram_base);
+ else
+ boot->free_pages(priv->ram_base, gd->ram_size >> 12);
+
+ efi_free(priv, (void *)gd->malloc_base);
+ efi_free(priv, gd);
+ global_data_ptr = NULL;
+}
+
+/**
+ * efi_main() - Start an EFI image
+ *
+ * This function is called by our EFI start-up code. It handles running
+ * U-Boot. If it returns, EFI will continue. Another way to get back to EFI
+ * is via reset_cpu().
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t image,
+ struct efi_system_table *sys_table)
+{
+ struct efi_priv local_priv, *priv = &local_priv;
+ efi_status_t ret;
+
+ /* Set up access to EFI data structures */
+ efi_init(priv, "App", image, sys_table);
+
+ global_priv = priv;
+
+ /*
+ * Set up the EFI debug UART so that printf() works. This is
+ * implemented in the EFI serial driver, serial_efi.c. The application
+ * can use printf() freely.
+ */
+ debug_uart_init();
+
+ ret = setup_memory(priv);
+ if (ret) {
+ printf("Failed to set up memory: ret=%lx\n", ret);
+ return ret;
+ }
+
+ printf("starting\n");
+
+ board_init_f(GD_FLG_SKIP_RELOC);
+ board_init_r(NULL, 0);
+ free_memory(priv);
+
+ return EFI_SUCCESS;
+}
+
+static void efi_exit(void)
+{
+ struct efi_priv *priv = global_priv;
+
+ free_memory(priv);
+ printf("U-Boot EFI exiting\n");
+ priv->boot->exit(priv->parent_image, EFI_SUCCESS, 0, NULL);
+}
+
+static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+ efi_exit();
+
+ return -EINPROGRESS;
+}
+
+static const struct udevice_id efi_sysreset_ids[] = {
+ { .compatible = "efi,reset" },
+ { }
+};
+
+static struct sysreset_ops efi_sysreset_ops = {
+ .request = efi_sysreset_request,
+};
+
+U_BOOT_DRIVER(efi_sysreset) = {
+ .name = "efi-sysreset",
+ .id = UCLASS_SYSRESET,
+ .of_match = efi_sysreset_ids,
+ .ops = &efi_sysreset_ops,
+};
diff --git a/lib/efi/efi_info.c b/lib/efi/efi_info.c
new file mode 100644
index 00000000..35a8a932
--- /dev/null
+++ b/lib/efi/efi_info.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * Access to the EFI information table
+ */
+
+#include <common.h>
+#include <efi.h>
+#include <errno.h>
+#include <mapmem.h>
+
+int efi_info_get(enum efi_entry_t type, void **datap, int *sizep)
+{
+ struct efi_entry_hdr *entry;
+ struct efi_info_hdr *info;
+ int ret;
+
+ if (!gd->arch.table)
+ return -ENODATA;
+
+ info = map_sysmem(gd->arch.table, 0);
+ if (info->version != EFI_TABLE_VERSION) {
+ ret = -EPROTONOSUPPORT;
+ goto err;
+ }
+
+ entry = (struct efi_entry_hdr *)((ulong)info + info->hdr_size);
+ while (entry->type != EFIET_END) {
+ if (entry->type == type) {
+ if (entry->addr)
+ *datap = map_sysmem(entry->addr, entry->size);
+ else
+ *datap = entry + 1;
+ *sizep = entry->size;
+ return 0;
+ }
+ entry = (struct efi_entry_hdr *)((ulong)entry + entry->link);
+ }
+
+ ret = -ENOENT;
+err:
+ unmap_sysmem(info);
+
+ return ret;
+}
diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c
new file mode 100644
index 00000000..6dd93ff4
--- /dev/null
+++ b/lib/efi/efi_stub.c
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * EFI information obtained here:
+ * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
+ *
+ * Loads a payload (U-Boot) within the EFI environment. This is built as an
+ * EFI application. It can be built either in 32-bit or 64-bit mode.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <errno.h>
+#include <ns16550.h>
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <linux/err.h>
+#include <linux/types.h>
+
+#ifndef CONFIG_X86
+/*
+ * Problem areas:
+ * - putc() uses the ns16550 address directly and assumed I/O access. Many
+ * platforms will use memory access
+ * get_codeseg32() is only meaningful on x86
+ */
+#error "This file needs to be ported for use on architectures"
+#endif
+
+static struct efi_priv *global_priv;
+static bool use_uart;
+
+struct __packed desctab_info {
+ uint16_t limit;
+ uint64_t addr;
+ uint16_t pad;
+};
+
+/*
+ * EFI uses Unicode and we don't. The easiest way to get a sensible output
+ * function is to use the U-Boot debug UART. We use EFI's console output
+ * function where available, and assume the built-in UART after that. We rely
+ * on EFI to set up the UART for us and just bring in the functions here.
+ * This last bit is a bit icky, but it's only for debugging anyway. We could
+ * build in ns16550.c with some effort, but this is a payload loader after
+ * all.
+ *
+ * Note: We avoid using printf() so we don't need to bring in lib/vsprintf.c.
+ * That would require some refactoring since we already build this for U-Boot.
+ * Building an EFI shared library version would have to be a separate stem.
+ * That might push us to using the SPL framework to build this stub. However
+ * that would involve a round of EFI-specific changes in SPL. Worth
+ * considering if we start needing more U-Boot functionality. Note that we
+ * could then move get_codeseg32() to arch/x86/cpu/cpu.c.
+ */
+void _debug_uart_init(void)
+{
+}
+
+void putc(const char ch)
+{
+ if (ch == '\n')
+ putc('\r');
+
+ if (use_uart) {
+ NS16550_t com_port = (NS16550_t)0x3f8;
+
+ while ((inb((ulong)&com_port->lsr) & UART_LSR_THRE) == 0)
+ ;
+ outb(ch, (ulong)&com_port->thr);
+ } else {
+ efi_putc(global_priv, ch);
+ }
+}
+
+void puts(const char *str)
+{
+ while (*str)
+ putc(*str++);
+}
+
+static void _debug_uart_putc(int ch)
+{
+ putc(ch);
+}
+
+DEBUG_UART_FUNCS
+
+void *memcpy(void *dest, const void *src, size_t size)
+{
+ unsigned char *dptr = dest;
+ const unsigned char *ptr = src;
+ const unsigned char *end = src + size;
+
+ while (ptr < end)
+ *dptr++ = *ptr++;
+
+ return dest;
+}
+
+void *memset(void *inptr, int ch, size_t size)
+{
+ char *ptr = inptr;
+ char *end = ptr + size;
+
+ while (ptr < end)
+ *ptr++ = ch;
+
+ return ptr;
+}
+
+static void jump_to_uboot(ulong cs32, ulong addr, ulong info)
+{
+#ifdef CONFIG_EFI_STUB_32BIT
+ /*
+ * U-Boot requires these parameters in registers, not on the stack.
+ * See _x86boot_start() for this code.
+ */
+ typedef void (*func_t)(int bist, int unused, ulong info)
+ __attribute__((regparm(3)));
+
+ ((func_t)addr)(0, 0, info);
+#else
+ cpu_call32(cs32, CONFIG_SYS_TEXT_BASE, info);
+#endif
+}
+
+#ifdef CONFIG_EFI_STUB_64BIT
+static void get_gdt(struct desctab_info *info)
+{
+ asm volatile ("sgdt %0" : : "m"(*info) : "memory");
+}
+#endif
+
+static inline unsigned long read_cr3(void)
+{
+ unsigned long val;
+
+ asm volatile("mov %%cr3,%0" : "=r" (val) : : "memory");
+ return val;
+}
+
+/**
+ * get_codeseg32() - Find the code segment to use for 32-bit code
+ *
+ * U-Boot only works in 32-bit mode at present, so when booting from 64-bit
+ * EFI we must first change to 32-bit mode. To do this we need to find the
+ * correct code segment to use (an entry in the Global Descriptor Table).
+ *
+ * @return code segment GDT offset, or 0 for 32-bit EFI, -ENOENT if not found
+ */
+static int get_codeseg32(void)
+{
+ int cs32 = 0;
+
+#ifdef CONFIG_EFI_STUB_64BIT
+ struct desctab_info gdt;
+ uint64_t *ptr;
+ int i;
+
+ get_gdt(&gdt);
+ for (ptr = (uint64_t *)(unsigned long)gdt.addr, i = 0; i < gdt.limit;
+ i += 8, ptr++) {
+ uint64_t desc = *ptr;
+ uint64_t base, limit;
+
+ /*
+ * Check that the target U-Boot jump address is within the
+ * selector and that the selector is of the right type.
+ */
+ base = ((desc >> GDT_BASE_LOW_SHIFT) & GDT_BASE_LOW_MASK) |
+ ((desc >> GDT_BASE_HIGH_SHIFT) & GDT_BASE_HIGH_MASK)
+ << 16;
+ limit = ((desc >> GDT_LIMIT_LOW_SHIFT) & GDT_LIMIT_LOW_MASK) |
+ ((desc >> GDT_LIMIT_HIGH_SHIFT) & GDT_LIMIT_HIGH_MASK)
+ << 16;
+ base <<= 12; /* 4KB granularity */
+ limit <<= 12;
+ if ((desc & GDT_PRESENT) && (desc & GDT_NOTSYS) &&
+ !(desc & GDT_LONG) && (desc & GDT_4KB) &&
+ (desc & GDT_32BIT) && (desc & GDT_CODE) &&
+ CONFIG_SYS_TEXT_BASE > base &&
+ CONFIG_SYS_TEXT_BASE + CONFIG_SYS_MONITOR_LEN < limit
+ ) {
+ cs32 = i;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ puts("\ngdt: ");
+ printhex8(gdt.limit);
+ puts(", addr: ");
+ printhex8(gdt.addr >> 32);
+ printhex8(gdt.addr);
+ for (i = 0; i < gdt.limit; i += 8) {
+ uint32_t *ptr = (uint32_t *)((unsigned long)gdt.addr + i);
+
+ puts("\n");
+ printhex2(i);
+ puts(": ");
+ printhex8(ptr[1]);
+ puts(" ");
+ printhex8(ptr[0]);
+ }
+ puts("\n ");
+ puts("32-bit code segment: ");
+ printhex2(cs32);
+ puts("\n ");
+
+ puts("page_table: ");
+ printhex8(read_cr3());
+ puts("\n ");
+#endif
+ if (!cs32) {
+ puts("Can't find 32-bit code segment\n");
+ return -ENOENT;
+ }
+#endif
+
+ return cs32;
+}
+
+static int setup_info_table(struct efi_priv *priv, int size)
+{
+ struct efi_info_hdr *info;
+ efi_status_t ret;
+
+ /* Get some memory for our info table */
+ priv->info_size = size;
+ info = efi_malloc(priv, priv->info_size, &ret);
+ if (ret) {
+ printhex2(ret);
+ puts(" No memory for info table: ");
+ return ret;
+ }
+
+ memset(info, '\0', sizeof(*info));
+ info->version = EFI_TABLE_VERSION;
+ info->hdr_size = sizeof(*info);
+ priv->info = info;
+ priv->next_hdr = (char *)info + info->hdr_size;
+
+ return 0;
+}
+
+static void add_entry_addr(struct efi_priv *priv, enum efi_entry_t type,
+ void *ptr1, int size1, void *ptr2, int size2)
+{
+ struct efi_entry_hdr *hdr = priv->next_hdr;
+
+ hdr->type = type;
+ hdr->size = size1 + size2;
+ hdr->addr = 0;
+ hdr->link = ALIGN(sizeof(*hdr) + hdr->size, 16);
+ priv->next_hdr += hdr->link;
+ memcpy(hdr + 1, ptr1, size1);
+ memcpy((void *)(hdr + 1) + size1, ptr2, size2);
+ priv->info->total_size = (ulong)priv->next_hdr - (ulong)priv->info;
+}
+
+/**
+ * efi_main() - Start an EFI image
+ *
+ * This function is called by our EFI start-up code. It handles running
+ * U-Boot. If it returns, EFI will continue.
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t image,
+ struct efi_system_table *sys_table)
+{
+ struct efi_priv local_priv, *priv = &local_priv;
+ struct efi_boot_services *boot = sys_table->boottime;
+ struct efi_mem_desc *desc;
+ struct efi_entry_memmap map;
+ struct efi_gop *gop;
+ struct efi_entry_gopmode mode;
+ struct efi_entry_systable table;
+ efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ efi_uintn_t key, desc_size, size;
+ efi_status_t ret;
+ u32 version;
+ int cs32;
+
+ ret = efi_init(priv, "Payload", image, sys_table);
+ if (ret) {
+ printhex2(ret);
+ puts(" efi_init() failed\n");
+ return ret;
+ }
+ global_priv = priv;
+
+ cs32 = get_codeseg32();
+ if (cs32 < 0)
+ return EFI_UNSUPPORTED;
+
+ /* Get the memory map so we can switch off EFI */
+ size = 0;
+ ret = boot->get_memory_map(&size, NULL, &key, &desc_size, &version);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ printhex2(EFI_BITS_PER_LONG);
+ putc(' ');
+ printhex2(ret);
+ puts(" No memory map\n");
+ return ret;
+ }
+ size += 1024; /* Since doing a malloc() may change the memory map! */
+ desc = efi_malloc(priv, size, &ret);
+ if (!desc) {
+ printhex2(ret);
+ puts(" No memory for memory descriptor\n");
+ return ret;
+ }
+ ret = setup_info_table(priv, size + 128);
+ if (ret)
+ return ret;
+
+ ret = boot->locate_protocol(&efi_gop_guid, NULL, (void **)&gop);
+ if (ret) {
+ puts(" GOP unavailable\n");
+ } else {
+ mode.fb_base = gop->mode->fb_base;
+ mode.fb_size = gop->mode->fb_size;
+ mode.info_size = gop->mode->info_size;
+ add_entry_addr(priv, EFIET_GOP_MODE, &mode, sizeof(mode),
+ gop->mode->info,
+ sizeof(struct efi_gop_mode_info));
+ }
+
+ ret = boot->get_memory_map(&size, desc, &key, &desc_size, &version);
+ if (ret) {
+ printhex2(ret);
+ puts(" Can't get memory map\n");
+ return ret;
+ }
+
+ table.sys_table = (ulong)sys_table;
+ add_entry_addr(priv, EFIET_SYS_TABLE, &table, sizeof(table), NULL, 0);
+
+ ret = boot->exit_boot_services(image, key);
+ if (ret) {
+ /*
+ * Unfortunately it happens that we cannot exit boot services
+ * the first time. But the second time it work. I don't know
+ * why but this seems to be a repeatable problem. To get
+ * around it, just try again.
+ */
+ printhex2(ret);
+ puts(" Can't exit boot services\n");
+ size = sizeof(desc);
+ ret = boot->get_memory_map(&size, desc, &key, &desc_size,
+ &version);
+ if (ret) {
+ printhex2(ret);
+ puts(" Can't get memory map\n");
+ return ret;
+ }
+ ret = boot->exit_boot_services(image, key);
+ if (ret) {
+ printhex2(ret);
+ puts(" Can't exit boot services 2\n");
+ return ret;
+ }
+ }
+
+ /* The EFI UART won't work now, switch to a debug one */
+ use_uart = true;
+
+ map.version = version;
+ map.desc_size = desc_size;
+ add_entry_addr(priv, EFIET_MEMORY_MAP, &map, sizeof(map), desc, size);
+ add_entry_addr(priv, EFIET_END, NULL, 0, 0, 0);
+
+ memcpy((void *)CONFIG_SYS_TEXT_BASE, _binary_u_boot_bin_start,
+ (ulong)_binary_u_boot_bin_end -
+ (ulong)_binary_u_boot_bin_start);
+
+#ifdef DEBUG
+ puts("EFI table at ");
+ printhex8((ulong)priv->info);
+ puts(" size ");
+ printhex8(priv->info->total_size);
+#endif
+ putc('\n');
+ jump_to_uboot(cs32, CONFIG_SYS_TEXT_BASE, (ulong)priv->info);
+
+ return EFI_LOAD_ERROR;
+}
diff --git a/lib/efi_driver/Makefile b/lib/efi_driver/Makefile
new file mode 100644
index 00000000..83baa1c9
--- /dev/null
+++ b/lib/efi_driver/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2017 Heinrich Schuchardt
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+obj-y += efi_uclass.o
+ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
+obj-y += efi_block_device.o
+endif
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c
new file mode 100644
index 00000000..cf023419
--- /dev/null
+++ b/lib/efi_driver/efi_block_device.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI block driver
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt
+ *
+ * The EFI uclass creates a handle for this driver and installs the
+ * driver binding protocol on it.
+ *
+ * The EFI block driver binds to controllers implementing the block io
+ * protocol.
+ *
+ * When the bind function of the EFI block driver is called it creates a
+ * new U-Boot block device. It installs child handles for all partitions and
+ * installs the simple file protocol on these.
+ *
+ * The read and write functions of the EFI block driver delegate calls to the
+ * controller that it is bound to.
+ *
+ * A usage example is as following:
+ *
+ * U-Boot loads the iPXE snp.efi executable. iPXE connects an iSCSI drive and
+ * exposes a handle with the block IO protocol. It calls ConnectController.
+ *
+ * Now the EFI block driver installs the partitions with the simple file
+ * protocol.
+ *
+ * iPXE uses the simple file protocol to load Grub or the Linux Kernel.
+ */
+
+#include <efi_driver.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+
+/*
+ * EFI attributes of the udevice handled by this driver.
+ *
+ * handle handle of the controller on which this driver is installed
+ * io block io protocol proxied by this driver
+ */
+struct efi_blk_platdata {
+ efi_handle_t handle;
+ struct efi_block_io *io;
+};
+
+/**
+ * Read from block device
+ *
+ * @dev: device
+ * @blknr: first block to be read
+ * @blkcnt: number of blocks to read
+ * @buffer: output buffer
+ * Return: number of blocks transferred
+ */
+static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+{
+ struct efi_blk_platdata *platdata = dev_get_platdata(dev);
+ struct efi_block_io *io = platdata->io;
+ efi_status_t ret;
+
+ EFI_PRINT("%s: read '%s', from block " LBAFU ", " LBAFU " blocks\n",
+ __func__, dev->name, blknr, blkcnt);
+ ret = EFI_CALL(io->read_blocks(
+ io, io->media->media_id, (u64)blknr,
+ (efi_uintn_t)blkcnt *
+ (efi_uintn_t)io->media->block_size, buffer));
+ EFI_PRINT("%s: r = %u\n", __func__,
+ (unsigned int)(ret & ~EFI_ERROR_MASK));
+ if (ret != EFI_SUCCESS)
+ return 0;
+ return blkcnt;
+}
+
+/**
+ * Write to block device
+ *
+ * @dev: device
+ * @blknr: first block to be write
+ * @blkcnt: number of blocks to write
+ * @buffer: input buffer
+ * Return: number of blocks transferred
+ */
+static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct efi_blk_platdata *platdata = dev_get_platdata(dev);
+ struct efi_block_io *io = platdata->io;
+ efi_status_t ret;
+
+ EFI_PRINT("%s: write '%s', from block " LBAFU ", " LBAFU " blocks\n",
+ __func__, dev->name, blknr, blkcnt);
+ ret = EFI_CALL(io->write_blocks(
+ io, io->media->media_id, (u64)blknr,
+ (efi_uintn_t)blkcnt *
+ (efi_uintn_t)io->media->block_size,
+ (void *)buffer));
+ EFI_PRINT("%s: r = %u\n", __func__,
+ (unsigned int)(ret & ~EFI_ERROR_MASK));
+ if (ret != EFI_SUCCESS)
+ return 0;
+ return blkcnt;
+}
+
+/**
+ * Create partions for the block device.
+ *
+ * @handle: EFI handle of the block device
+ * @dev: udevice of the block device
+ * Return: number of partitions created
+ */
+static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev)
+{
+ struct blk_desc *desc;
+ const char *if_typename;
+
+ desc = dev_get_uclass_platdata(dev);
+ if_typename = blk_get_if_type_name(desc->if_type);
+
+ return efi_disk_create_partitions(handle, desc, if_typename,
+ desc->devnum, dev->name);
+}
+
+/**
+ * Create a block device for a handle
+ *
+ * @handle: handle
+ * @interface: block io protocol
+ * Return: 0 = success
+ */
+static int efi_bl_bind(efi_handle_t handle, void *interface)
+{
+ struct udevice *bdev, *parent = dm_root();
+ int ret, devnum;
+ char *name;
+ struct efi_object *obj = efi_search_obj(handle);
+ struct efi_block_io *io = interface;
+ int disks;
+ struct efi_blk_platdata *platdata;
+
+ EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
+
+ if (!obj)
+ return -ENOENT;
+
+ devnum = blk_find_max_devnum(IF_TYPE_EFI);
+ if (devnum == -ENODEV)
+ devnum = 0;
+ else if (devnum < 0)
+ return devnum;
+
+ name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
+ if (!name)
+ return -ENOMEM;
+ sprintf(name, "efiblk#%d", devnum);
+
+ /* Create driver model udevice for the EFI block io device */
+ ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum,
+ io->media->block_size,
+ (lbaint_t)io->media->last_block, &bdev);
+ if (ret)
+ return ret;
+ if (!bdev)
+ return -ENOENT;
+ /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
+ device_set_name_alloced(bdev);
+
+ platdata = dev_get_platdata(bdev);
+ platdata->handle = handle;
+ platdata->io = interface;
+
+ ret = device_probe(bdev);
+ if (ret)
+ return ret;
+ EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
+
+ /* Create handles for the partions of the block device */
+ disks = efi_bl_bind_partitions(handle, bdev);
+ EFI_PRINT("Found %d partitions\n", disks);
+
+ return 0;
+}
+
+/* Block device driver operators */
+static const struct blk_ops efi_blk_ops = {
+ .read = efi_bl_read,
+ .write = efi_bl_write,
+};
+
+/* Identify as block device driver */
+U_BOOT_DRIVER(efi_blk) = {
+ .name = "efi_blk",
+ .id = UCLASS_BLK,
+ .ops = &efi_blk_ops,
+ .platdata_auto_alloc_size = sizeof(struct efi_blk_platdata),
+};
+
+/* EFI driver operators */
+static const struct efi_driver_ops driver_ops = {
+ .protocol = &efi_block_io_guid,
+ .child_protocol = &efi_block_io_guid,
+ .bind = efi_bl_bind,
+};
+
+/* Identify as EFI driver */
+U_BOOT_DRIVER(efi_block) = {
+ .name = "EFI block driver",
+ .id = UCLASS_EFI,
+ .ops = &driver_ops,
+};
diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
new file mode 100644
index 00000000..b14746e6
--- /dev/null
+++ b/lib/efi_driver/efi_uclass.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Uclass for EFI drivers
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt
+ *
+ * For each EFI driver the uclass
+ * - creates a handle
+ * - installs the driver binding protocol
+ *
+ * The uclass provides the bind, start, and stop entry points for the driver
+ * binding protocol.
+ *
+ * In bind() and stop() it checks if the controller implements the protocol
+ * supported by the EFI driver. In the start() function it calls the bind()
+ * function of the EFI driver. In the stop() function it destroys the child
+ * controllers.
+ */
+
+#include <efi_driver.h>
+
+/**
+ * check_node_type() - check node type
+ *
+ * We do not support partitions as controller handles.
+ *
+ * @handle: handle to be checked
+ * Return: status code
+ */
+static efi_status_t check_node_type(efi_handle_t handle)
+{
+ efi_status_t r, ret = EFI_SUCCESS;
+ const struct efi_device_path *dp;
+
+ /* Open the device path protocol */
+ r = EFI_CALL(systab.boottime->open_protocol(
+ handle, &efi_guid_device_path, (void **)&dp,
+ NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (r == EFI_SUCCESS && dp) {
+ /* Get the last node */
+ const struct efi_device_path *node = efi_dp_last_node(dp);
+ /* We do not support partitions as controller */
+ if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE)
+ ret = EFI_UNSUPPORTED;
+ }
+ return ret;
+}
+
+/**
+ * efi_uc_supported() - check if the driver supports the controller
+ *
+ * @this: driver binding protocol
+ * @controller_handle: handle of the controller
+ * @remaining_device_path: path specifying the child controller
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uc_supported(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ struct efi_device_path *remaining_device_path)
+{
+ efi_status_t r, ret;
+ void *interface;
+ struct efi_driver_binding_extended_protocol *bp =
+ (struct efi_driver_binding_extended_protocol *)this;
+
+ EFI_ENTRY("%p, %p, %ls", this, controller_handle,
+ efi_dp_str(remaining_device_path));
+
+ ret = EFI_CALL(systab.boottime->open_protocol(
+ controller_handle, bp->ops->protocol,
+ &interface, this->driver_binding_handle,
+ controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
+ switch (ret) {
+ case EFI_ACCESS_DENIED:
+ case EFI_ALREADY_STARTED:
+ goto out;
+ case EFI_SUCCESS:
+ break;
+ default:
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ ret = check_node_type(controller_handle);
+
+ r = EFI_CALL(systab.boottime->close_protocol(
+ controller_handle, bp->ops->protocol,
+ this->driver_binding_handle,
+ controller_handle));
+ if (r != EFI_SUCCESS)
+ ret = EFI_UNSUPPORTED;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_uc_start() - create child controllers and attach driver
+ *
+ * @this: driver binding protocol
+ * @controller_handle: handle of the controller
+ * @remaining_device_path: path specifying the child controller
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uc_start(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ struct efi_device_path *remaining_device_path)
+{
+ efi_status_t r, ret;
+ void *interface = NULL;
+ struct efi_driver_binding_extended_protocol *bp =
+ (struct efi_driver_binding_extended_protocol *)this;
+
+ EFI_ENTRY("%p, %pUl, %ls", this, controller_handle,
+ efi_dp_str(remaining_device_path));
+
+ /* Attach driver to controller */
+ ret = EFI_CALL(systab.boottime->open_protocol(
+ controller_handle, bp->ops->protocol,
+ &interface, this->driver_binding_handle,
+ controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
+ switch (ret) {
+ case EFI_ACCESS_DENIED:
+ case EFI_ALREADY_STARTED:
+ goto out;
+ case EFI_SUCCESS:
+ break;
+ default:
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ ret = check_node_type(controller_handle);
+ if (ret != EFI_SUCCESS) {
+ r = EFI_CALL(systab.boottime->close_protocol(
+ controller_handle, bp->ops->protocol,
+ this->driver_binding_handle,
+ controller_handle));
+ if (r != EFI_SUCCESS)
+ EFI_PRINT("Failure to close handle\n");
+ goto out;
+ }
+
+ /* TODO: driver specific stuff */
+ bp->ops->bind(controller_handle, interface);
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * disconnect_child() - remove a single child controller from the parent
+ * controller
+ *
+ * @controller_handle: parent controller
+ * @child_handle: child controller
+ * Return: status code
+ */
+static efi_status_t disconnect_child(efi_handle_t controller_handle,
+ efi_handle_t child_handle)
+{
+ efi_status_t ret;
+ efi_guid_t *guid_controller = NULL;
+ efi_guid_t *guid_child_controller = NULL;
+
+ ret = EFI_CALL(systab.boottime->close_protocol(
+ controller_handle, guid_controller,
+ child_handle, child_handle));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("Cannot close protocol\n");
+ return ret;
+ }
+ ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
+ child_handle, guid_child_controller, NULL));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("Cannot uninstall protocol interface\n");
+ return ret;
+ }
+ return ret;
+}
+
+/**
+ * efi_uc_stop() - Remove child controllers and disconnect the controller
+ *
+ * @this: driver binding protocol
+ * @controller_handle: handle of the controller
+ * @number_of_children: number of child controllers to remove
+ * @child_handle_buffer: handles of the child controllers to remove
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uc_stop(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ size_t number_of_children,
+ efi_handle_t *child_handle_buffer)
+{
+ efi_status_t ret;
+ efi_uintn_t count;
+ struct efi_open_protocol_info_entry *entry_buffer;
+ efi_guid_t *guid_controller = NULL;
+
+ EFI_ENTRY("%p, %pUl, %zu, %p", this, controller_handle,
+ number_of_children, child_handle_buffer);
+
+ /* Destroy provided child controllers */
+ if (number_of_children) {
+ efi_uintn_t i;
+
+ for (i = 0; i < number_of_children; ++i) {
+ ret = disconnect_child(controller_handle,
+ child_handle_buffer[i]);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ return EFI_SUCCESS;
+ }
+
+ /* Destroy all children */
+ ret = EFI_CALL(systab.boottime->open_protocol_information(
+ controller_handle, guid_controller,
+ &entry_buffer, &count));
+ if (ret != EFI_SUCCESS)
+ goto out;
+ while (count) {
+ if (entry_buffer[--count].attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ ret = disconnect_child(
+ controller_handle,
+ entry_buffer[count].agent_handle);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ }
+ }
+ ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
+ if (ret != EFI_SUCCESS)
+ printf("%s: ERROR: Cannot free pool\n", __func__);
+
+ /* Detach driver from controller */
+ ret = EFI_CALL(systab.boottime->close_protocol(
+ controller_handle, guid_controller,
+ this->driver_binding_handle, controller_handle));
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_add_driver() - add driver
+ *
+ * @drv: driver to add
+ * Return: status code
+ */
+static efi_status_t efi_add_driver(struct driver *drv)
+{
+ efi_status_t ret;
+ const struct efi_driver_ops *ops = drv->ops;
+ struct efi_driver_binding_extended_protocol *bp;
+
+ debug("EFI: Adding driver '%s'\n", drv->name);
+ if (!ops->protocol) {
+ printf("EFI: ERROR: protocol GUID missing for driver '%s'\n",
+ drv->name);
+ return EFI_INVALID_PARAMETER;
+ }
+ bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
+ if (!bp)
+ return EFI_OUT_OF_RESOURCES;
+
+ bp->bp.supported = efi_uc_supported;
+ bp->bp.start = efi_uc_start;
+ bp->bp.stop = efi_uc_stop;
+ bp->bp.version = 0xffffffff;
+ bp->ops = drv->ops;
+
+ ret = efi_create_handle(&bp->bp.driver_binding_handle);
+ if (ret != EFI_SUCCESS) {
+ free(bp);
+ goto out;
+ }
+ bp->bp.image_handle = bp->bp.driver_binding_handle;
+ ret = efi_add_protocol(bp->bp.driver_binding_handle,
+ &efi_guid_driver_binding_protocol, bp);
+ if (ret != EFI_SUCCESS) {
+ efi_delete_handle(bp->bp.driver_binding_handle);
+ free(bp);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+/**
+ * efi_driver_init() - initialize the EFI drivers
+ *
+ * Called by efi_init_obj_list().
+ *
+ * Return: 0 = success, any other value will stop further execution
+ */
+efi_status_t efi_driver_init(void)
+{
+ struct driver *drv;
+ efi_status_t ret = EFI_SUCCESS;
+
+ debug("EFI: Initializing EFI driver framework\n");
+ for (drv = ll_entry_start(struct driver, driver);
+ drv < ll_entry_end(struct driver, driver); ++drv) {
+ if (drv->id == UCLASS_EFI) {
+ ret = efi_add_driver(drv);
+ if (ret != EFI_SUCCESS) {
+ printf("EFI: ERROR: failed to add driver %s\n",
+ drv->name);
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/**
+ * efi_uc_init() - initialize the EFI uclass
+ *
+ * @class: the EFI uclass
+ * Return: 0 = success
+ */
+static int efi_uc_init(struct uclass *class)
+{
+ printf("EFI: Initializing UCLASS_EFI\n");
+ return 0;
+}
+
+/**
+ * efi_uc_destroy() - destroy the EFI uclass
+ *
+ * @class: the EFI uclass
+ * Return: 0 = success
+ */
+static int efi_uc_destroy(struct uclass *class)
+{
+ printf("Destroying UCLASS_EFI\n");
+ return 0;
+}
+
+UCLASS_DRIVER(efi) = {
+ .name = "efi",
+ .id = UCLASS_EFI,
+ .init = efi_uc_init,
+ .destroy = efi_uc_destroy,
+};
diff --git a/lib/efi_loader/.gitignore b/lib/efi_loader/.gitignore
new file mode 100644
index 00000000..634a600f
--- /dev/null
+++ b/lib/efi_loader/.gitignore
@@ -0,0 +1,2 @@
+*.efi
+*.so
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
new file mode 100644
index 00000000..21ef4403
--- /dev/null
+++ b/lib/efi_loader/Kconfig
@@ -0,0 +1,123 @@
+config EFI_LOADER
+ bool "Support running UEFI applications"
+ depends on OF_LIBFDT && ( \
+ ARM && (SYS_CPU = arm1136 || \
+ SYS_CPU = arm1176 || \
+ SYS_CPU = armv7 || \
+ SYS_CPU = armv8) || \
+ X86 || RISCV || SANDBOX)
+ # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB
+ depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT
+ # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB
+ depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT
+ default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8
+ select LIB_UUID
+ select HAVE_BLOCK_DEVICE
+ select REGEX
+ imply CFB_CONSOLE_ANSI
+ help
+ Select this option if you want to run UEFI applications (like GNU
+ GRUB or iPXE) on top of U-Boot. If this option is enabled, U-Boot
+ will expose the UEFI API to a loaded application, enabling it to
+ reuse U-Boot's device drivers.
+
+if EFI_LOADER
+
+config EFI_GET_TIME
+ bool "GetTime() runtime service"
+ depends on DM_RTC
+ default y
+ help
+ Provide the GetTime() runtime service at boottime. This service
+ can be used by an EFI application to read the real time clock.
+
+config EFI_SET_TIME
+ bool "SetTime() runtime service"
+ depends on EFI_GET_TIME
+ default n
+ help
+ Provide the SetTime() runtime service at boottime. This service
+ can be used by an EFI application to adjust the real time clock.
+
+config EFI_DEVICE_PATH_TO_TEXT
+ bool "Device path to text protocol"
+ default y
+ help
+ The device path to text protocol converts device nodes and paths to
+ human readable strings.
+
+config EFI_LOADER_HII
+ bool "HII protocols"
+ default y
+ help
+ The Human Interface Infrastructure is a complicated framework that
+ allows UEFI applications to draw fancy menus and hook strings using
+ a translation framework.
+
+ U-Boot implements enough of its features to be able to run the UEFI
+ Shell, but not more than that.
+
+config EFI_UNICODE_COLLATION_PROTOCOL2
+ bool "Unicode collation protocol"
+ default y
+ help
+ The Unicode collation protocol is used for lexical comparisons. It is
+ required to run the UEFI shell.
+
+if EFI_UNICODE_COLLATION_PROTOCOL2
+
+config EFI_UNICODE_CAPITALIZATION
+ bool "Support Unicode capitalization"
+ default y
+ help
+ Select this option to enable correct handling of the capitalization of
+ Unicode codepoints in the range 0x0000-0xffff. If this option is not
+ set, only the the correct handling of the letters of the codepage
+ used by the FAT file system is ensured.
+
+config EFI_UNICODE_COLLATION_PROTOCOL
+ bool "Deprecated version of the Unicode collation protocol"
+ default n
+ help
+ In EFI 1.10 a version of the Unicode collation protocol using ISO
+ 639-2 language codes existed. This protocol is not part of the UEFI
+ specification any longer. Unfortunately it is required to run the
+ UEFI Self Certification Test (SCT) II, version 2.6, 2017.
+
+ Choose this option for testing only. It is bound to be removed.
+
+endif
+
+config EFI_LOADER_BOUNCE_BUFFER
+ bool "EFI Applications use bounce buffers for DMA operations"
+ depends on ARM64
+ default n
+ help
+ Some hardware does not support DMA to full 64bit addresses. For this
+ hardware we can create a bounce buffer so that payloads don't have to
+ worry about platform details.
+
+config EFI_PLATFORM_LANG_CODES
+ string "Language codes supported by firmware"
+ default "en-US"
+ help
+ This value is used to initialize the PlatformLangCodes variable. Its
+ value is a semicolon (;) separated list of language codes in native
+ RFC 4646 format, e.g. "en-US;de-DE". The first language code is used
+ to initialize the PlatformLang variable.
+
+config EFI_HAVE_RUNTIME_RESET
+ # bool "Reset runtime service is available"
+ bool
+ default y
+ depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || SYSRESET_X86
+
+config EFI_GRUB_ARM32_WORKAROUND
+ bool "Workaround for GRUB on 32bit ARM"
+ default y
+ depends on ARM && !ARM64
+ help
+ GRUB prior to version 2.04 requires U-Boot to disable caches. This
+ workaround currently is also needed on systems with caches that
+ cannot be managed via CP15.
+endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
new file mode 100644
index 00000000..7db40602
--- /dev/null
+++ b/lib/efi_loader/Makefile
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Alexander Graf
+#
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+asflags-y += -DHOST_ARCH="$(HOST_ARCH)"
+ccflags-y += -DHOST_ARCH="$(HOST_ARCH)"
+
+CFLAGS_efi_boottime.o += \
+ -DFW_VERSION="0x$(VERSION)" \
+ -DFW_PATCHLEVEL="0x$(PATCHLEVEL)"
+CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI)
+
+ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
+always += helloworld.efi
+endif
+
+obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
+obj-y += efi_bootmgr.o
+obj-y += efi_boottime.o
+obj-y += efi_console.o
+obj-y += efi_device_path.o
+obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
+obj-y += efi_device_path_utilities.o
+obj-y += efi_file.o
+obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o efi_hii_config.o
+obj-y += efi_image_loader.o
+obj-y += efi_memory.o
+obj-y += efi_root_node.o
+obj-y += efi_runtime.o
+obj-y += efi_setup.o
+obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
+obj-y += efi_variable.o
+obj-y += efi_watchdog.o
+obj-$(CONFIG_LCD) += efi_gop.o
+obj-$(CONFIG_DM_VIDEO) += efi_gop.o
+obj-$(CONFIG_PARTITIONS) += efi_disk.o
+obj-$(CONFIG_NET) += efi_net.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
+obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c
new file mode 100644
index 00000000..a4e5e53d
--- /dev/null
+++ b/lib/efi_loader/efi_acpi.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application ACPI tables support
+ *
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <asm/acpi_table.h>
+
+static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
+
+/*
+ * Install the ACPI table as a configuration table.
+ *
+ * @return status code
+ */
+efi_status_t efi_acpi_register(void)
+{
+ /* Map within the low 32 bits, to allow for 32bit ACPI tables */
+ u64 acpi = U32_MAX;
+ efi_status_t ret;
+
+ /* Reserve 64kiB page for ACPI */
+ ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+ EFI_RUNTIME_SERVICES_DATA, 16, &acpi);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ /*
+ * Generate ACPI tables - we know that efi_allocate_pages() returns
+ * a 4k-aligned address, so it is safe to assume that
+ * write_acpi_tables() will write the table at that address.
+ */
+ assert(!(acpi & 0xf));
+ write_acpi_tables(acpi);
+
+ /* And expose them to our EFI payload */
+ return efi_install_configuration_table(&acpi_guid,
+ (void *)(uintptr_t)acpi);
+}
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
new file mode 100644
index 00000000..2ea21448
--- /dev/null
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI boot manager
+ *
+ * Copyright (c) 2017 Rob Clark
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <malloc.h>
+#include <efi_loader.h>
+#include <asm/unaligned.h>
+
+static const struct efi_boot_services *bs;
+static const struct efi_runtime_services *rs;
+
+/*
+ * bootmgr implements the logic of trying to find a payload to boot
+ * based on the BootOrder + BootXXXX variables, and then loading it.
+ *
+ * TODO detecting a special key held (f9?) and displaying a boot menu
+ * like you would get on a PC would be clever.
+ *
+ * TODO if we had a way to write and persist variables after the OS
+ * has started, we'd also want to check OsIndications to see if we
+ * should do normal or recovery boot.
+ */
+
+
+/**
+ * efi_deserialize_load_option() - parse serialized data
+ *
+ * Parse serialized data describing a load option and transform it to the
+ * efi_load_option structure.
+ *
+ * @lo: pointer to target
+ * @data: serialized data
+ */
+void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data)
+{
+ lo->attributes = get_unaligned_le32(data);
+ data += sizeof(u32);
+
+ lo->file_path_length = get_unaligned_le16(data);
+ data += sizeof(u16);
+
+ /* FIXME */
+ lo->label = (u16 *)data;
+ data += (u16_strlen(lo->label) + 1) * sizeof(u16);
+
+ /* FIXME */
+ lo->file_path = (struct efi_device_path *)data;
+ data += lo->file_path_length;
+
+ lo->optional_data = data;
+}
+
+/**
+ * efi_serialize_load_option() - serialize load option
+ *
+ * Serialize efi_load_option structure into byte stream for BootXXXX.
+ *
+ * @data: buffer for serialized data
+ * @lo: load option
+ * Return: size of allocated buffer
+ */
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
+{
+ unsigned long label_len;
+ unsigned long size;
+ u8 *p;
+
+ label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
+
+ /* total size */
+ size = sizeof(lo->attributes);
+ size += sizeof(lo->file_path_length);
+ size += label_len;
+ size += lo->file_path_length;
+ if (lo->optional_data)
+ size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ + 1) * sizeof(u16);
+ p = malloc(size);
+ if (!p)
+ return 0;
+
+ /* copy data */
+ *data = p;
+ memcpy(p, &lo->attributes, sizeof(lo->attributes));
+ p += sizeof(lo->attributes);
+
+ memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
+ p += sizeof(lo->file_path_length);
+
+ memcpy(p, lo->label, label_len);
+ p += label_len;
+
+ memcpy(p, lo->file_path, lo->file_path_length);
+ p += lo->file_path_length;
+
+ if (lo->optional_data) {
+ utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
+ p += sizeof(u16); /* size of trailing \0 */
+ }
+ return size;
+}
+
+/**
+ * get_var() - get UEFI variable
+ *
+ * It is the caller's duty to free the returned buffer.
+ *
+ * @name: name of variable
+ * @vendor: vendor GUID of variable
+ * @size: size of allocated buffer
+ * Return: buffer with variable data or NULL
+ */
+static void *get_var(u16 *name, const efi_guid_t *vendor,
+ efi_uintn_t *size)
+{
+ efi_guid_t *v = (efi_guid_t *)vendor;
+ efi_status_t ret;
+ void *buf = NULL;
+
+ *size = 0;
+ EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ buf = malloc(*size);
+ EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
+ }
+
+ if (ret != EFI_SUCCESS) {
+ free(buf);
+ *size = 0;
+ return NULL;
+ }
+
+ return buf;
+}
+
+/**
+ * try_load_entry() - try to load image for boot option
+ *
+ * Attempt to load load-option number 'n', returning device_path and file_path
+ * if successful. This checks that the EFI_LOAD_OPTION is active (enabled)
+ * and that the specified file to boot exists.
+ *
+ * @n: number of the boot option, e.g. 0x0a13 for Boot0A13
+ * @handle: on return handle for the newly installed image
+ * Return: status code
+ */
+static efi_status_t try_load_entry(u16 n, efi_handle_t *handle)
+{
+ struct efi_load_option lo;
+ u16 varname[] = L"Boot0000";
+ u16 hexmap[] = L"0123456789ABCDEF";
+ void *load_option;
+ efi_uintn_t size;
+ efi_status_t ret;
+
+ varname[4] = hexmap[(n & 0xf000) >> 12];
+ varname[5] = hexmap[(n & 0x0f00) >> 8];
+ varname[6] = hexmap[(n & 0x00f0) >> 4];
+ varname[7] = hexmap[(n & 0x000f) >> 0];
+
+ load_option = get_var(varname, &efi_global_variable_guid, &size);
+ if (!load_option)
+ return EFI_LOAD_ERROR;
+
+ efi_deserialize_load_option(&lo, load_option);
+
+ if (lo.attributes & LOAD_OPTION_ACTIVE) {
+ u32 attributes;
+
+ debug("%s: trying to load \"%ls\" from %pD\n",
+ __func__, lo.label, lo.file_path);
+
+ ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
+ NULL, 0, handle));
+ if (ret != EFI_SUCCESS) {
+ printf("Loading from Boot%04X '%ls' failed\n", n,
+ lo.label);
+ goto error;
+ }
+
+ attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
+ size = sizeof(n);
+ ret = EFI_CALL(efi_set_variable(
+ L"BootCurrent",
+ (efi_guid_t *)&efi_global_variable_guid,
+ attributes, size, &n));
+ if (ret != EFI_SUCCESS) {
+ if (EFI_CALL(efi_unload_image(*handle))
+ != EFI_SUCCESS)
+ printf("Unloading image failed\n");
+ goto error;
+ }
+
+ printf("Booting: %ls\n", lo.label);
+ } else {
+ ret = EFI_LOAD_ERROR;
+ }
+
+error:
+ free(load_option);
+
+ return ret;
+}
+
+/**
+ * efi_bootmgr_load() - try to load from BootNext or BootOrder
+ *
+ * Attempt to load from BootNext or in the order specified by BootOrder
+ * EFI variable, the available load-options, finding and returning
+ * the first one that can be loaded successfully.
+ *
+ * @handle: on return handle for the newly installed image
+ * Return: status code
+ */
+efi_status_t efi_bootmgr_load(efi_handle_t *handle)
+{
+ u16 bootnext, *bootorder;
+ efi_uintn_t size;
+ int i, num;
+ efi_status_t ret;
+
+ bs = systab.boottime;
+ rs = systab.runtime;
+
+ /* BootNext */
+ bootnext = 0;
+ size = sizeof(bootnext);
+ ret = EFI_CALL(efi_get_variable(L"BootNext",
+ (efi_guid_t *)&efi_global_variable_guid,
+ NULL, &size, &bootnext));
+ if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
+ /* BootNext does exist here */
+ if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16))
+ printf("BootNext must be 16-bit integer\n");
+
+ /* delete BootNext */
+ ret = EFI_CALL(efi_set_variable(
+ L"BootNext",
+ (efi_guid_t *)&efi_global_variable_guid,
+ EFI_VARIABLE_NON_VOLATILE, 0,
+ &bootnext));
+
+ /* load BootNext */
+ if (ret == EFI_SUCCESS) {
+ if (size == sizeof(u16)) {
+ ret = try_load_entry(bootnext, handle);
+ if (ret == EFI_SUCCESS)
+ return ret;
+ printf("Loading from BootNext failed, falling back to BootOrder\n");
+ }
+ } else {
+ printf("Deleting BootNext failed\n");
+ }
+ }
+
+ /* BootOrder */
+ bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size);
+ if (!bootorder) {
+ printf("BootOrder not defined\n");
+ ret = EFI_NOT_FOUND;
+ goto error;
+ }
+
+ num = size / sizeof(uint16_t);
+ for (i = 0; i < num; i++) {
+ debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]);
+ ret = try_load_entry(bootorder[i], handle);
+ if (ret == EFI_SUCCESS)
+ break;
+ }
+
+ free(bootorder);
+
+error:
+ return ret;
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
new file mode 100644
index 00000000..88a7604b
--- /dev/null
+++ b/lib/efi_loader/efi_boottime.c
@@ -0,0 +1,3678 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application boot time services
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <efi_loader.h>
+#include <irq_func.h>
+#include <malloc.h>
+#include <time.h>
+#include <linux/libfdt_env.h>
+#include <u-boot/crc.h>
+#include <bootm.h>
+#include <pe.h>
+#include <u-boot/crc.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Task priority level */
+static efi_uintn_t efi_tpl = TPL_APPLICATION;
+
+/* This list contains all the EFI objects our payload has access to */
+LIST_HEAD(efi_obj_list);
+
+/* List of all events */
+__efi_runtime_data LIST_HEAD(efi_events);
+
+/* List of queued events */
+LIST_HEAD(efi_event_queue);
+
+/* Flag to disable timer activity in ExitBootServices() */
+static bool timers_enabled = true;
+
+/* List of all events registered by RegisterProtocolNotify() */
+LIST_HEAD(efi_register_notify_events);
+
+/* Handle of the currently executing image */
+static efi_handle_t current_image;
+
+#ifdef CONFIG_ARM
+/*
+ * The "gd" pointer lives in a register on ARM and AArch64 that we declare
+ * fixed when compiling U-Boot. However, the payload does not know about that
+ * restriction so we need to manually swap its and our view of that register on
+ * EFI callback entry/exit.
+ */
+static volatile void *efi_gd, *app_gd;
+#endif
+
+/* 1 if inside U-Boot code, 0 if inside EFI payload code */
+static int entry_count = 1;
+static int nesting_level;
+/* GUID of the device tree table */
+const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
+/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
+const efi_guid_t efi_guid_driver_binding_protocol =
+ EFI_DRIVER_BINDING_PROTOCOL_GUID;
+
+/* event group ExitBootServices() invoked */
+const efi_guid_t efi_guid_event_group_exit_boot_services =
+ EFI_EVENT_GROUP_EXIT_BOOT_SERVICES;
+/* event group SetVirtualAddressMap() invoked */
+const efi_guid_t efi_guid_event_group_virtual_address_change =
+ EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE;
+/* event group memory map changed */
+const efi_guid_t efi_guid_event_group_memory_map_change =
+ EFI_EVENT_GROUP_MEMORY_MAP_CHANGE;
+/* event group boot manager about to boot */
+const efi_guid_t efi_guid_event_group_ready_to_boot =
+ EFI_EVENT_GROUP_READY_TO_BOOT;
+/* event group ResetSystem() invoked (before ExitBootServices) */
+const efi_guid_t efi_guid_event_group_reset_system =
+ EFI_EVENT_GROUP_RESET_SYSTEM;
+
+static efi_status_t EFIAPI efi_disconnect_controller(
+ efi_handle_t controller_handle,
+ efi_handle_t driver_image_handle,
+ efi_handle_t child_handle);
+
+/* Called on every callback entry */
+int __efi_entry_check(void)
+{
+ int ret = entry_count++ == 0;
+#ifdef CONFIG_ARM
+ assert(efi_gd);
+ app_gd = gd;
+ gd = efi_gd;
+#endif
+ return ret;
+}
+
+/* Called on every callback exit */
+int __efi_exit_check(void)
+{
+ int ret = --entry_count == 0;
+#ifdef CONFIG_ARM
+ gd = app_gd;
+#endif
+ return ret;
+}
+
+/* Called from do_bootefi_exec() */
+void efi_save_gd(void)
+{
+#ifdef CONFIG_ARM
+ efi_gd = gd;
+#endif
+}
+
+/*
+ * Special case handler for error/abort that just forces things back to u-boot
+ * world so we can dump out an abort message, without any care about returning
+ * back to UEFI world.
+ */
+void efi_restore_gd(void)
+{
+#ifdef CONFIG_ARM
+ /* Only restore if we're already in EFI context */
+ if (!efi_gd)
+ return;
+ gd = efi_gd;
+#endif
+}
+
+/**
+ * indent_string() - returns a string for indenting with two spaces per level
+ * @level: indent level
+ *
+ * A maximum of ten indent levels is supported. Higher indent levels will be
+ * truncated.
+ *
+ * Return: A string for indenting with two spaces per level is
+ * returned.
+ */
+static const char *indent_string(int level)
+{
+ const char *indent = " ";
+ const int max = strlen(indent);
+
+ level = min(max, level * 2);
+ return &indent[max - level];
+}
+
+const char *__efi_nesting(void)
+{
+ return indent_string(nesting_level);
+}
+
+const char *__efi_nesting_inc(void)
+{
+ return indent_string(nesting_level++);
+}
+
+const char *__efi_nesting_dec(void)
+{
+ return indent_string(--nesting_level);
+}
+
+/**
+ * efi_event_is_queued() - check if an event is queued
+ *
+ * @event: event
+ * Return: true if event is queued
+ */
+static bool efi_event_is_queued(struct efi_event *event)
+{
+ return !!event->queue_link.next;
+}
+
+/**
+ * efi_process_event_queue() - process event queue
+ */
+static void efi_process_event_queue(void)
+{
+ while (!list_empty(&efi_event_queue)) {
+ struct efi_event *event;
+ efi_uintn_t old_tpl;
+
+ event = list_first_entry(&efi_event_queue, struct efi_event,
+ queue_link);
+ if (efi_tpl >= event->notify_tpl)
+ return;
+ list_del(&event->queue_link);
+ event->queue_link.next = NULL;
+ event->queue_link.prev = NULL;
+ /* Events must be executed at the event's TPL */
+ old_tpl = efi_tpl;
+ efi_tpl = event->notify_tpl;
+ EFI_CALL_VOID(event->notify_function(event,
+ event->notify_context));
+ efi_tpl = old_tpl;
+ if (event->type == EVT_NOTIFY_SIGNAL)
+ event->is_signaled = 0;
+ }
+}
+
+/**
+ * efi_queue_event() - queue an EFI event
+ * @event: event to signal
+ *
+ * This function queues the notification function of the event for future
+ * execution.
+ *
+ */
+static void efi_queue_event(struct efi_event *event)
+{
+ struct efi_event *item = NULL;
+
+ if (!event->notify_function)
+ return;
+
+ if (!efi_event_is_queued(event)) {
+ /*
+ * Events must be notified in order of decreasing task priority
+ * level. Insert the new event accordingly.
+ */
+ list_for_each_entry(item, &efi_event_queue, queue_link) {
+ if (item->notify_tpl < event->notify_tpl) {
+ list_add_tail(&event->queue_link,
+ &item->queue_link);
+ event = NULL;
+ break;
+ }
+ }
+ if (event)
+ list_add_tail(&event->queue_link, &efi_event_queue);
+ }
+ efi_process_event_queue();
+}
+
+/**
+ * is_valid_tpl() - check if the task priority level is valid
+ *
+ * @tpl: TPL level to check
+ * Return: status code
+ */
+efi_status_t is_valid_tpl(efi_uintn_t tpl)
+{
+ switch (tpl) {
+ case TPL_APPLICATION:
+ case TPL_CALLBACK:
+ case TPL_NOTIFY:
+ case TPL_HIGH_LEVEL:
+ return EFI_SUCCESS;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ * efi_signal_event() - signal an EFI event
+ * @event: event to signal
+ *
+ * This function signals an event. If the event belongs to an event group all
+ * events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
+ * their notification function is queued.
+ *
+ * For the SignalEvent service see efi_signal_event_ext.
+ */
+void efi_signal_event(struct efi_event *event)
+{
+ if (event->is_signaled)
+ return;
+ if (event->group) {
+ struct efi_event *evt;
+
+ /*
+ * The signaled state has to set before executing any
+ * notification function
+ */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (!evt->group || guidcmp(evt->group, event->group))
+ continue;
+ if (evt->is_signaled)
+ continue;
+ evt->is_signaled = true;
+ }
+ list_for_each_entry(evt, &efi_events, link) {
+ if (!evt->group || guidcmp(evt->group, event->group))
+ continue;
+ efi_queue_event(evt);
+ }
+ } else {
+ event->is_signaled = true;
+ efi_queue_event(event);
+ }
+}
+
+/**
+ * efi_raise_tpl() - raise the task priority level
+ * @new_tpl: new value of the task priority level
+ *
+ * This function implements the RaiseTpl service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: old value of the task priority level
+ */
+static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl)
+{
+ efi_uintn_t old_tpl = efi_tpl;
+
+ EFI_ENTRY("0x%zx", new_tpl);
+
+ if (new_tpl < efi_tpl)
+ EFI_PRINT("WARNING: new_tpl < current_tpl in %s\n", __func__);
+ efi_tpl = new_tpl;
+ if (efi_tpl > TPL_HIGH_LEVEL)
+ efi_tpl = TPL_HIGH_LEVEL;
+
+ EFI_EXIT(EFI_SUCCESS);
+ return old_tpl;
+}
+
+/**
+ * efi_restore_tpl() - lower the task priority level
+ * @old_tpl: value of the task priority level to be restored
+ *
+ * This function implements the RestoreTpl service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl)
+{
+ EFI_ENTRY("0x%zx", old_tpl);
+
+ if (old_tpl > efi_tpl)
+ EFI_PRINT("WARNING: old_tpl > current_tpl in %s\n", __func__);
+ efi_tpl = old_tpl;
+ if (efi_tpl > TPL_HIGH_LEVEL)
+ efi_tpl = TPL_HIGH_LEVEL;
+
+ /*
+ * Lowering the TPL may have made queued events eligible for execution.
+ */
+ efi_timer_check();
+
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_allocate_pages_ext() - allocate memory pages
+ * @type: type of allocation to be performed
+ * @memory_type: usage type of the allocated memory
+ * @pages: number of pages to be allocated
+ * @memory: allocated memory
+ *
+ * This function implements the AllocatePages service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
+ efi_uintn_t pages,
+ uint64_t *memory)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%d, %d, 0x%zx, %p", type, memory_type, pages, memory);
+ r = efi_allocate_pages(type, memory_type, pages, memory);
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_free_pages_ext() - Free memory pages.
+ * @memory: start of the memory area to be freed
+ * @pages: number of pages to be freed
+ *
+ * This function implements the FreePages service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory,
+ efi_uintn_t pages)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%llx, 0x%zx", memory, pages);
+ r = efi_free_pages(memory, pages);
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_get_memory_map_ext() - get map describing memory usage
+ * @memory_map_size: on entry the size, in bytes, of the memory map buffer,
+ * on exit the size of the copied memory map
+ * @memory_map: buffer to which the memory map is written
+ * @map_key: key for the memory map
+ * @descriptor_size: size of an individual memory descriptor
+ * @descriptor_version: version number of the memory descriptor structure
+ *
+ * This function implements the GetMemoryMap service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_get_memory_map_ext(
+ efi_uintn_t *memory_map_size,
+ struct efi_mem_desc *memory_map,
+ efi_uintn_t *map_key,
+ efi_uintn_t *descriptor_size,
+ uint32_t *descriptor_version)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%p, %p, %p, %p, %p", memory_map_size, memory_map,
+ map_key, descriptor_size, descriptor_version);
+ r = efi_get_memory_map(memory_map_size, memory_map, map_key,
+ descriptor_size, descriptor_version);
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_allocate_pool_ext() - allocate memory from pool
+ * @pool_type: type of the pool from which memory is to be allocated
+ * @size: number of bytes to be allocated
+ * @buffer: allocated memory
+ *
+ * This function implements the AllocatePool service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
+ efi_uintn_t size,
+ void **buffer)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%d, %zd, %p", pool_type, size, buffer);
+ r = efi_allocate_pool(pool_type, size, buffer);
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_free_pool_ext() - free memory from pool
+ * @buffer: start of memory to be freed
+ *
+ * This function implements the FreePool service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%p", buffer);
+ r = efi_free_pool(buffer);
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_add_handle() - add a new handle to the object list
+ *
+ * @handle: handle to be added
+ *
+ * The protocols list is initialized. The handle is added to the list of known
+ * UEFI objects.
+ */
+void efi_add_handle(efi_handle_t handle)
+{
+ if (!handle)
+ return;
+ INIT_LIST_HEAD(&handle->protocols);
+ list_add_tail(&handle->link, &efi_obj_list);
+}
+
+/**
+ * efi_create_handle() - create handle
+ * @handle: new handle
+ *
+ * Return: status code
+ */
+efi_status_t efi_create_handle(efi_handle_t *handle)
+{
+ struct efi_object *obj;
+
+ obj = calloc(1, sizeof(struct efi_object));
+ if (!obj)
+ return EFI_OUT_OF_RESOURCES;
+
+ efi_add_handle(obj);
+ *handle = obj;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_search_protocol() - find a protocol on a handle.
+ * @handle: handle
+ * @protocol_guid: GUID of the protocol
+ * @handler: reference to the protocol
+ *
+ * Return: status code
+ */
+efi_status_t efi_search_protocol(const efi_handle_t handle,
+ const efi_guid_t *protocol_guid,
+ struct efi_handler **handler)
+{
+ struct efi_object *efiobj;
+ struct list_head *lhandle;
+
+ if (!handle || !protocol_guid)
+ return EFI_INVALID_PARAMETER;
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ list_for_each(lhandle, &efiobj->protocols) {
+ struct efi_handler *protocol;
+
+ protocol = list_entry(lhandle, struct efi_handler, link);
+ if (!guidcmp(protocol->guid, protocol_guid)) {
+ if (handler)
+ *handler = protocol;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ * efi_remove_protocol() - delete protocol from a handle
+ * @handle: handle from which the protocol shall be deleted
+ * @protocol: GUID of the protocol to be deleted
+ * @protocol_interface: interface of the protocol implementation
+ *
+ * Return: status code
+ */
+efi_status_t efi_remove_protocol(const efi_handle_t handle,
+ const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ struct efi_handler *handler;
+ efi_status_t ret;
+
+ ret = efi_search_protocol(handle, protocol, &handler);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (handler->protocol_interface != protocol_interface)
+ return EFI_NOT_FOUND;
+ list_del(&handler->link);
+ free(handler);
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_remove_all_protocols() - delete all protocols from a handle
+ * @handle: handle from which the protocols shall be deleted
+ *
+ * Return: status code
+ */
+efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *protocol;
+ struct efi_handler *pos;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
+ efi_status_t ret;
+
+ ret = efi_remove_protocol(handle, protocol->guid,
+ protocol->protocol_interface);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_delete_handle() - delete handle
+ *
+ * @handle: handle to delete
+ */
+void efi_delete_handle(efi_handle_t handle)
+{
+ if (!handle)
+ return;
+ efi_remove_all_protocols(handle);
+ list_del(&handle->link);
+ free(handle);
+}
+
+/**
+ * efi_is_event() - check if a pointer is a valid event
+ * @event: pointer to check
+ *
+ * Return: status code
+ */
+static efi_status_t efi_is_event(const struct efi_event *event)
+{
+ const struct efi_event *evt;
+
+ if (!event)
+ return EFI_INVALID_PARAMETER;
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt == event)
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ * efi_create_event() - create an event
+ *
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @group: event group
+ * @event: created event
+ *
+ * This function is used inside U-Boot code to create an event.
+ *
+ * For the API function implementing the CreateEvent service see
+ * efi_create_event_ext.
+ *
+ * Return: status code
+ */
+efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
+ void (EFIAPI *notify_function) (
+ struct efi_event *event,
+ void *context),
+ void *notify_context, efi_guid_t *group,
+ struct efi_event **event)
+{
+ struct efi_event *evt;
+ efi_status_t ret;
+ int pool_type;
+
+ if (event == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ switch (type) {
+ case 0:
+ case EVT_TIMER:
+ case EVT_NOTIFY_SIGNAL:
+ case EVT_TIMER | EVT_NOTIFY_SIGNAL:
+ case EVT_NOTIFY_WAIT:
+ case EVT_TIMER | EVT_NOTIFY_WAIT:
+ case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+ pool_type = EFI_BOOT_SERVICES_DATA;
+ break;
+ case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+ pool_type = EFI_RUNTIME_SERVICES_DATA;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) &&
+ (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS))
+ return EFI_INVALID_PARAMETER;
+
+ ret = efi_allocate_pool(pool_type, sizeof(struct efi_event),
+ (void **)&evt);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ memset(evt, 0, sizeof(struct efi_event));
+ evt->type = type;
+ evt->notify_tpl = notify_tpl;
+ evt->notify_function = notify_function;
+ evt->notify_context = notify_context;
+ evt->group = group;
+ /* Disable timers on boot up */
+ evt->trigger_next = -1ULL;
+ list_add_tail(&evt->link, &efi_events);
+ *event = evt;
+ return EFI_SUCCESS;
+}
+
+/*
+ * efi_create_event_ex() - create an event in a group
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @event: created event
+ * @event_group: event group
+ *
+ * This function implements the CreateEventEx service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
+ void (EFIAPI *notify_function) (
+ struct efi_event *event,
+ void *context),
+ void *notify_context,
+ efi_guid_t *event_group,
+ struct efi_event **event)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
+ notify_context, event_group);
+
+ /*
+ * The allowable input parameters are the same as in CreateEvent()
+ * except for the following two disallowed event types.
+ */
+ switch (type) {
+ case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+ case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_create_event(type, notify_tpl, notify_function,
+ notify_context, event_group, event);
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_create_event_ext() - create an event
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @event: created event
+ *
+ * This function implements the CreateEvent service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_create_event_ext(
+ uint32_t type, efi_uintn_t notify_tpl,
+ void (EFIAPI *notify_function) (
+ struct efi_event *event,
+ void *context),
+ void *notify_context, struct efi_event **event)
+{
+ EFI_ENTRY("%d, 0x%zx, %p, %p", type, notify_tpl, notify_function,
+ notify_context);
+ return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
+ notify_context, NULL, event));
+}
+
+/**
+ * efi_timer_check() - check if a timer event has occurred
+ *
+ * Check if a timer event has occurred or a queued notification function should
+ * be called.
+ *
+ * Our timers have to work without interrupts, so we check whenever keyboard
+ * input or disk accesses happen if enough time elapsed for them to fire.
+ */
+void efi_timer_check(void)
+{
+ struct efi_event *evt;
+ u64 now = timer_get_us();
+
+ list_for_each_entry(evt, &efi_events, link) {
+ if (!timers_enabled)
+ continue;
+ if (!(evt->type & EVT_TIMER) || now < evt->trigger_next)
+ continue;
+ switch (evt->trigger_type) {
+ case EFI_TIMER_RELATIVE:
+ evt->trigger_type = EFI_TIMER_STOP;
+ break;
+ case EFI_TIMER_PERIODIC:
+ evt->trigger_next += evt->trigger_time;
+ break;
+ default:
+ continue;
+ }
+ evt->is_signaled = false;
+ efi_signal_event(evt);
+ }
+ efi_process_event_queue();
+ WATCHDOG_RESET();
+}
+
+/**
+ * efi_set_timer() - set the trigger time for a timer event or stop the event
+ * @event: event for which the timer is set
+ * @type: type of the timer
+ * @trigger_time: trigger period in multiples of 100 ns
+ *
+ * This is the function for internal usage in U-Boot. For the API function
+ * implementing the SetTimer service see efi_set_timer_ext.
+ *
+ * Return: status code
+ */
+efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
+ uint64_t trigger_time)
+{
+ /* Check that the event is valid */
+ if (efi_is_event(event) != EFI_SUCCESS || !(event->type & EVT_TIMER))
+ return EFI_INVALID_PARAMETER;
+
+ /*
+ * The parameter defines a multiple of 100 ns.
+ * We use multiples of 1000 ns. So divide by 10.
+ */
+ do_div(trigger_time, 10);
+
+ switch (type) {
+ case EFI_TIMER_STOP:
+ event->trigger_next = -1ULL;
+ break;
+ case EFI_TIMER_PERIODIC:
+ case EFI_TIMER_RELATIVE:
+ event->trigger_next = timer_get_us() + trigger_time;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ event->trigger_type = type;
+ event->trigger_time = trigger_time;
+ event->is_signaled = false;
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_set_timer_ext() - Set the trigger time for a timer event or stop the
+ * event
+ * @event: event for which the timer is set
+ * @type: type of the timer
+ * @trigger_time: trigger period in multiples of 100 ns
+ *
+ * This function implements the SetTimer service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event,
+ enum efi_timer_delay type,
+ uint64_t trigger_time)
+{
+ EFI_ENTRY("%p, %d, %llx", event, type, trigger_time);
+ return EFI_EXIT(efi_set_timer(event, type, trigger_time));
+}
+
+/**
+ * efi_wait_for_event() - wait for events to be signaled
+ * @num_events: number of events to be waited for
+ * @event: events to be waited for
+ * @index: index of the event that was signaled
+ *
+ * This function implements the WaitForEvent service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
+ struct efi_event **event,
+ efi_uintn_t *index)
+{
+ int i;
+
+ EFI_ENTRY("%zd, %p, %p", num_events, event, index);
+
+ /* Check parameters */
+ if (!num_events || !event)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ /* Check TPL */
+ if (efi_tpl != TPL_APPLICATION)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+ for (i = 0; i < num_events; ++i) {
+ if (efi_is_event(event[i]) != EFI_SUCCESS)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ if (!event[i]->is_signaled)
+ efi_queue_event(event[i]);
+ }
+
+ /* Wait for signal */
+ for (;;) {
+ for (i = 0; i < num_events; ++i) {
+ if (event[i]->is_signaled)
+ goto out;
+ }
+ /* Allow events to occur. */
+ efi_timer_check();
+ }
+
+out:
+ /*
+ * Reset the signal which is passed to the caller to allow periodic
+ * events to occur.
+ */
+ event[i]->is_signaled = false;
+ if (index)
+ *index = i;
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_signal_event_ext() - signal an EFI event
+ * @event: event to signal
+ *
+ * This function implements the SignalEvent service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * This functions sets the signaled state of the event and queues the
+ * notification function for execution.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
+{
+ EFI_ENTRY("%p", event);
+ if (efi_is_event(event) != EFI_SUCCESS)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ efi_signal_event(event);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_close_event() - close an EFI event
+ * @event: event to close
+ *
+ * This function implements the CloseEvent service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
+{
+ struct efi_register_notify_event *item, *next;
+
+ EFI_ENTRY("%p", event);
+ if (efi_is_event(event) != EFI_SUCCESS)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* Remove protocol notify registrations for the event */
+ list_for_each_entry_safe(item, next, &efi_register_notify_events,
+ link) {
+ if (event == item->event) {
+ struct efi_protocol_notification *hitem, *hnext;
+
+ /* Remove signaled handles */
+ list_for_each_entry_safe(hitem, hnext, &item->handles,
+ link) {
+ list_del(&hitem->link);
+ free(hitem);
+ }
+ list_del(&item->link);
+ free(item);
+ }
+ }
+ /* Remove event from queue */
+ if (efi_event_is_queued(event))
+ list_del(&event->queue_link);
+
+ list_del(&event->link);
+ efi_free_pool(event);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_check_event() - check if an event is signaled
+ * @event: event to check
+ *
+ * This function implements the CheckEvent service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * If an event is not signaled yet, the notification function is queued. The
+ * signaled state is cleared.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
+{
+ EFI_ENTRY("%p", event);
+ efi_timer_check();
+ if (efi_is_event(event) != EFI_SUCCESS ||
+ event->type & EVT_NOTIFY_SIGNAL)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ if (!event->is_signaled)
+ efi_queue_event(event);
+ if (event->is_signaled) {
+ event->is_signaled = false;
+ return EFI_EXIT(EFI_SUCCESS);
+ }
+ return EFI_EXIT(EFI_NOT_READY);
+}
+
+/**
+ * efi_search_obj() - find the internal EFI object for a handle
+ * @handle: handle to find
+ *
+ * Return: EFI object
+ */
+struct efi_object *efi_search_obj(const efi_handle_t handle)
+{
+ struct efi_object *efiobj;
+
+ if (!handle)
+ return NULL;
+
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ if (efiobj == handle)
+ return efiobj;
+ }
+ return NULL;
+}
+
+/**
+ * efi_open_protocol_info_entry() - create open protocol info entry and add it
+ * to a protocol
+ * @handler: handler of a protocol
+ *
+ * Return: open protocol info entry
+ */
+static struct efi_open_protocol_info_entry *efi_create_open_info(
+ struct efi_handler *handler)
+{
+ struct efi_open_protocol_info_item *item;
+
+ item = calloc(1, sizeof(struct efi_open_protocol_info_item));
+ if (!item)
+ return NULL;
+ /* Append the item to the open protocol info list. */
+ list_add_tail(&item->link, &handler->open_infos);
+
+ return &item->info;
+}
+
+/**
+ * efi_delete_open_info() - remove an open protocol info entry from a protocol
+ * @item: open protocol info entry to delete
+ *
+ * Return: status code
+ */
+static efi_status_t efi_delete_open_info(
+ struct efi_open_protocol_info_item *item)
+{
+ list_del(&item->link);
+ free(item);
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_add_protocol() - install new protocol on a handle
+ * @handle: handle on which the protocol shall be installed
+ * @protocol: GUID of the protocol to be installed
+ * @protocol_interface: interface of the protocol implementation
+ *
+ * Return: status code
+ */
+efi_status_t efi_add_protocol(const efi_handle_t handle,
+ const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+ efi_status_t ret;
+ struct efi_register_notify_event *event;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ ret = efi_search_protocol(handle, protocol, NULL);
+ if (ret != EFI_NOT_FOUND)
+ return EFI_INVALID_PARAMETER;
+ handler = calloc(1, sizeof(struct efi_handler));
+ if (!handler)
+ return EFI_OUT_OF_RESOURCES;
+ handler->guid = protocol;
+ handler->protocol_interface = protocol_interface;
+ INIT_LIST_HEAD(&handler->open_infos);
+ list_add_tail(&handler->link, &efiobj->protocols);
+
+ /* Notify registered events */
+ list_for_each_entry(event, &efi_register_notify_events, link) {
+ if (!guidcmp(protocol, &event->protocol)) {
+ struct efi_protocol_notification *notif;
+
+ notif = calloc(1, sizeof(*notif));
+ if (!notif) {
+ list_del(&handler->link);
+ free(handler);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ notif->handle = handle;
+ list_add_tail(&notif->link, &event->handles);
+ event->event->is_signaled = false;
+ efi_signal_event(event->event);
+ }
+ }
+
+ if (!guidcmp(&efi_guid_device_path, protocol))
+ EFI_PRINT("installed device path '%pD'\n", protocol_interface);
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_install_protocol_interface() - install protocol interface
+ * @handle: handle on which the protocol shall be installed
+ * @protocol: GUID of the protocol to be installed
+ * @protocol_interface_type: type of the interface to be installed,
+ * always EFI_NATIVE_INTERFACE
+ * @protocol_interface: interface of the protocol implementation
+ *
+ * This function implements the InstallProtocolInterface service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_install_protocol_interface(
+ efi_handle_t *handle, const efi_guid_t *protocol,
+ int protocol_interface_type, void *protocol_interface)
+{
+ efi_status_t r;
+
+ EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type,
+ protocol_interface);
+
+ if (!handle || !protocol ||
+ protocol_interface_type != EFI_NATIVE_INTERFACE) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Create new handle if requested. */
+ if (!*handle) {
+ r = efi_create_handle(handle);
+ if (r != EFI_SUCCESS)
+ goto out;
+ EFI_PRINT("new handle %p\n", *handle);
+ } else {
+ EFI_PRINT("handle %p\n", *handle);
+ }
+ /* Add new protocol */
+ r = efi_add_protocol(*handle, protocol, protocol_interface);
+out:
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_get_drivers() - get all drivers associated to a controller
+ * @handle: handle of the controller
+ * @protocol: protocol GUID (optional)
+ * @number_of_drivers: number of child controllers
+ * @driver_handle_buffer: handles of the the drivers
+ *
+ * The allocated buffer has to be freed with free().
+ *
+ * Return: status code
+ */
+static efi_status_t efi_get_drivers(efi_handle_t handle,
+ const efi_guid_t *protocol,
+ efi_uintn_t *number_of_drivers,
+ efi_handle_t **driver_handle_buffer)
+{
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+ efi_uintn_t count = 0, i;
+ bool duplicate;
+
+ /* Count all driver associations */
+ list_for_each_entry(handler, &handle->protocols, link) {
+ if (protocol && guidcmp(handler->guid, protocol))
+ continue;
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_DRIVER)
+ ++count;
+ }
+ }
+ *number_of_drivers = 0;
+ if (!count) {
+ *driver_handle_buffer = NULL;
+ return EFI_SUCCESS;
+ }
+ /*
+ * Create buffer. In case of duplicate driver assignments the buffer
+ * will be too large. But that does not harm.
+ */
+ *driver_handle_buffer = calloc(count, sizeof(efi_handle_t));
+ if (!*driver_handle_buffer)
+ return EFI_OUT_OF_RESOURCES;
+ /* Collect unique driver handles */
+ list_for_each_entry(handler, &handle->protocols, link) {
+ if (protocol && guidcmp(handler->guid, protocol))
+ continue;
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ /* Check this is a new driver */
+ duplicate = false;
+ for (i = 0; i < *number_of_drivers; ++i) {
+ if ((*driver_handle_buffer)[i] ==
+ item->info.agent_handle)
+ duplicate = true;
+ }
+ /* Copy handle to buffer */
+ if (!duplicate) {
+ i = (*number_of_drivers)++;
+ (*driver_handle_buffer)[i] =
+ item->info.agent_handle;
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_disconnect_all_drivers() - disconnect all drivers from a controller
+ * @handle: handle of the controller
+ * @protocol: protocol GUID (optional)
+ * @child_handle: handle of the child to destroy
+ *
+ * This function implements the DisconnectController service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_disconnect_all_drivers
+ (efi_handle_t handle,
+ const efi_guid_t *protocol,
+ efi_handle_t child_handle)
+{
+ efi_uintn_t number_of_drivers;
+ efi_handle_t *driver_handle_buffer;
+ efi_status_t r, ret;
+
+ ret = efi_get_drivers(handle, protocol, &number_of_drivers,
+ &driver_handle_buffer);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (!number_of_drivers)
+ return EFI_SUCCESS;
+ ret = EFI_NOT_FOUND;
+ while (number_of_drivers) {
+ r = EFI_CALL(efi_disconnect_controller(
+ handle,
+ driver_handle_buffer[--number_of_drivers],
+ child_handle));
+ if (r == EFI_SUCCESS)
+ ret = r;
+ }
+ free(driver_handle_buffer);
+ return ret;
+}
+
+/**
+ * efi_uninstall_protocol() - uninstall protocol interface
+ *
+ * @handle: handle from which the protocol shall be removed
+ * @protocol: GUID of the protocol to be removed
+ * @protocol_interface: interface to be removed
+ *
+ * This function DOES NOT delete a handle without installed protocol.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_uninstall_protocol
+ (efi_handle_t handle, const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+ struct efi_open_protocol_info_item *pos;
+ efi_status_t r;
+
+ /* Check handle */
+ efiobj = efi_search_obj(handle);
+ if (!efiobj) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /* Find the protocol on the handle */
+ r = efi_search_protocol(handle, protocol, &handler);
+ if (r != EFI_SUCCESS)
+ goto out;
+ /* Disconnect controllers */
+ efi_disconnect_all_drivers(efiobj, protocol, NULL);
+ /* Close protocol */
+ list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
+ if (item->info.attributes ==
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ||
+ item->info.attributes == EFI_OPEN_PROTOCOL_GET_PROTOCOL ||
+ item->info.attributes == EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+ list_del(&item->link);
+ }
+ if (!list_empty(&handler->open_infos)) {
+ r = EFI_ACCESS_DENIED;
+ goto out;
+ }
+ r = efi_remove_protocol(handle, protocol, protocol_interface);
+out:
+ return r;
+}
+
+/**
+ * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * @handle: handle from which the protocol shall be removed
+ * @protocol: GUID of the protocol to be removed
+ * @protocol_interface: interface to be removed
+ *
+ * This function implements the UninstallProtocolInterface service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uninstall_protocol_interface
+ (efi_handle_t handle, const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
+
+ ret = efi_uninstall_protocol(handle, protocol, protocol_interface);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* If the last protocol has been removed, delete the handle. */
+ if (list_empty(&handle->protocols)) {
+ list_del(&handle->link);
+ free(handle);
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_register_protocol_notify() - register an event for notification when a
+ * protocol is installed.
+ * @protocol: GUID of the protocol whose installation shall be notified
+ * @event: event to be signaled upon installation of the protocol
+ * @registration: key for retrieving the registration information
+ *
+ * This function implements the RegisterProtocolNotify service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_register_protocol_notify(
+ const efi_guid_t *protocol,
+ struct efi_event *event,
+ void **registration)
+{
+ struct efi_register_notify_event *item;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
+
+ if (!protocol || !event || !registration) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ item = calloc(1, sizeof(struct efi_register_notify_event));
+ if (!item) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ item->event = event;
+ memcpy(&item->protocol, protocol, sizeof(efi_guid_t));
+ INIT_LIST_HEAD(&item->handles);
+
+ list_add_tail(&item->link, &efi_register_notify_events);
+
+ *registration = item;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_search() - determine if an EFI handle implements a protocol
+ *
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @handle: handle
+ *
+ * See the documentation of the LocateHandle service in the UEFI specification.
+ *
+ * Return: 0 if the handle implements the protocol
+ */
+static int efi_search(enum efi_locate_search_type search_type,
+ const efi_guid_t *protocol, efi_handle_t handle)
+{
+ efi_status_t ret;
+
+ switch (search_type) {
+ case ALL_HANDLES:
+ return 0;
+ case BY_PROTOCOL:
+ ret = efi_search_protocol(handle, protocol, NULL);
+ return (ret != EFI_SUCCESS);
+ default:
+ /* Invalid search type */
+ return -1;
+ }
+}
+
+/**
+ * efi_check_register_notify_event() - check if registration key is valid
+ *
+ * Check that a pointer is a valid registration key as returned by
+ * RegisterProtocolNotify().
+ *
+ * @key: registration key
+ * Return: valid registration key or NULL
+ */
+static struct efi_register_notify_event *efi_check_register_notify_event
+ (void *key)
+{
+ struct efi_register_notify_event *event;
+
+ list_for_each_entry(event, &efi_register_notify_events, link) {
+ if (event == (struct efi_register_notify_event *)key)
+ return event;
+ }
+ return NULL;
+}
+
+/**
+ * efi_locate_handle() - locate handles implementing a protocol
+ *
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @buffer_size: size of the buffer to receive the handles in bytes
+ * @buffer: buffer to receive the relevant handles
+ *
+ * This function is meant for U-Boot internal calls. For the API implementation
+ * of the LocateHandle service see efi_locate_handle_ext.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_locate_handle(
+ enum efi_locate_search_type search_type,
+ const efi_guid_t *protocol, void *search_key,
+ efi_uintn_t *buffer_size, efi_handle_t *buffer)
+{
+ struct efi_object *efiobj;
+ efi_uintn_t size = 0;
+ struct efi_register_notify_event *event;
+ struct efi_protocol_notification *handle = NULL;
+
+ /* Check parameters */
+ switch (search_type) {
+ case ALL_HANDLES:
+ break;
+ case BY_REGISTER_NOTIFY:
+ if (!search_key)
+ return EFI_INVALID_PARAMETER;
+ /* Check that the registration key is valid */
+ event = efi_check_register_notify_event(search_key);
+ if (!event)
+ return EFI_INVALID_PARAMETER;
+ break;
+ case BY_PROTOCOL:
+ if (!protocol)
+ return EFI_INVALID_PARAMETER;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Count how much space we need */
+ if (search_type == BY_REGISTER_NOTIFY) {
+ if (list_empty(&event->handles))
+ return EFI_NOT_FOUND;
+ handle = list_first_entry(&event->handles,
+ struct efi_protocol_notification,
+ link);
+ efiobj = handle->handle;
+ size += sizeof(void *);
+ } else {
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ if (!efi_search(search_type, protocol, efiobj))
+ size += sizeof(void *);
+ }
+ if (size == 0)
+ return EFI_NOT_FOUND;
+ }
+
+ if (!buffer_size)
+ return EFI_INVALID_PARAMETER;
+
+ if (*buffer_size < size) {
+ *buffer_size = size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *buffer_size = size;
+
+ /* The buffer size is sufficient but there is no buffer */
+ if (!buffer)
+ return EFI_INVALID_PARAMETER;
+
+ /* Then fill the array */
+ if (search_type == BY_REGISTER_NOTIFY) {
+ *buffer = efiobj;
+ list_del(&handle->link);
+ } else {
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ if (!efi_search(search_type, protocol, efiobj))
+ *buffer++ = efiobj;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_locate_handle_ext() - locate handles implementing a protocol.
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @buffer_size: size of the buffer to receive the handles in bytes
+ * @buffer: buffer to receive the relevant handles
+ *
+ * This function implements the LocateHandle service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: 0 if the handle implements the protocol
+ */
+static efi_status_t EFIAPI efi_locate_handle_ext(
+ enum efi_locate_search_type search_type,
+ const efi_guid_t *protocol, void *search_key,
+ efi_uintn_t *buffer_size, efi_handle_t *buffer)
+{
+ EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
+ buffer_size, buffer);
+
+ return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
+ buffer_size, buffer));
+}
+
+/**
+ * efi_remove_configuration_table() - collapses configuration table entries,
+ * removing index i
+ *
+ * @i: index of the table entry to be removed
+ */
+static void efi_remove_configuration_table(int i)
+{
+ struct efi_configuration_table *this = &systab.tables[i];
+ struct efi_configuration_table *next = &systab.tables[i + 1];
+ struct efi_configuration_table *end = &systab.tables[systab.nr_tables];
+
+ memmove(this, next, (ulong)end - (ulong)next);
+ systab.nr_tables--;
+}
+
+/**
+ * efi_install_configuration_table() - adds, updates, or removes a
+ * configuration table
+ * @guid: GUID of the installed table
+ * @table: table to be installed
+ *
+ * This function is used for internal calls. For the API implementation of the
+ * InstallConfigurationTable service see efi_install_configuration_table_ext.
+ *
+ * Return: status code
+ */
+efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
+ void *table)
+{
+ struct efi_event *evt;
+ int i;
+
+ if (!guid)
+ return EFI_INVALID_PARAMETER;
+
+ /* Check for GUID override */
+ for (i = 0; i < systab.nr_tables; i++) {
+ if (!guidcmp(guid, &systab.tables[i].guid)) {
+ if (table)
+ systab.tables[i].table = table;
+ else
+ efi_remove_configuration_table(i);
+ goto out;
+ }
+ }
+
+ if (!table)
+ return EFI_NOT_FOUND;
+
+ /* No override, check for overflow */
+ if (i >= EFI_MAX_CONFIGURATION_TABLES)
+ return EFI_OUT_OF_RESOURCES;
+
+ /* Add a new entry */
+ memcpy(&systab.tables[i].guid, guid, sizeof(*guid));
+ systab.tables[i].table = table;
+ systab.nr_tables = i + 1;
+
+out:
+ /* systab.nr_tables may have changed. So we need to update the CRC32 */
+ efi_update_table_header_crc32(&systab.hdr);
+
+ /* Notify that the configuration table was changed */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group && !guidcmp(evt->group, guid)) {
+ efi_signal_event(evt);
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_install_configuration_table_ex() - Adds, updates, or removes a
+ * configuration table.
+ * @guid: GUID of the installed table
+ * @table: table to be installed
+ *
+ * This function implements the InstallConfigurationTable service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
+ void *table)
+{
+ EFI_ENTRY("%pUl, %p", guid, table);
+ return EFI_EXIT(efi_install_configuration_table(guid, table));
+}
+
+/**
+ * efi_setup_loaded_image() - initialize a loaded image
+ *
+ * Initialize a loaded_image_info and loaded_image_info object with correct
+ * protocols, boot-device, etc.
+ *
+ * In case of an error \*handle_ptr and \*info_ptr are set to NULL and an error
+ * code is returned.
+ *
+ * @device_path: device path of the loaded image
+ * @file_path: file path of the loaded image
+ * @handle_ptr: handle of the loaded image
+ * @info_ptr: loaded image protocol
+ * Return: status code
+ */
+efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+ struct efi_device_path *file_path,
+ struct efi_loaded_image_obj **handle_ptr,
+ struct efi_loaded_image **info_ptr)
+{
+ efi_status_t ret;
+ struct efi_loaded_image *info = NULL;
+ struct efi_loaded_image_obj *obj = NULL;
+ struct efi_device_path *dp;
+
+ /* In case of EFI_OUT_OF_RESOURCES avoid illegal free by caller. */
+ *handle_ptr = NULL;
+ *info_ptr = NULL;
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return EFI_OUT_OF_RESOURCES;
+ obj = calloc(1, sizeof(*obj));
+ if (!obj) {
+ free(info);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ obj->header.type = EFI_OBJECT_TYPE_LOADED_IMAGE;
+
+ /* Add internal object to object list */
+ efi_add_handle(&obj->header);
+
+ info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
+ info->file_path = file_path;
+ info->system_table = &systab;
+
+ if (device_path) {
+ info->device_handle = efi_dp_find_obj(device_path, NULL);
+
+ dp = efi_dp_append(device_path, file_path);
+ if (!dp) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto failure;
+ }
+ } else {
+ dp = NULL;
+ }
+ ret = efi_add_protocol(&obj->header,
+ &efi_guid_loaded_image_device_path, dp);
+ if (ret != EFI_SUCCESS)
+ goto failure;
+
+ /*
+ * When asking for the loaded_image interface, just
+ * return handle which points to loaded_image_info
+ */
+ ret = efi_add_protocol(&obj->header,
+ &efi_guid_loaded_image, info);
+ if (ret != EFI_SUCCESS)
+ goto failure;
+
+ *info_ptr = info;
+ *handle_ptr = obj;
+
+ return ret;
+failure:
+ printf("ERROR: Failure to install protocols for loaded image\n");
+ efi_delete_handle(&obj->header);
+ free(info);
+ return ret;
+}
+
+/**
+ * efi_load_image_from_path() - load an image using a file path
+ *
+ * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
+ * callers obligation to update the memory type as needed.
+ *
+ * @file_path: the path of the image to load
+ * @buffer: buffer containing the loaded image
+ * @size: size of the loaded image
+ * Return: status code
+ */
+static
+efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
+ void **buffer, efi_uintn_t *size)
+{
+ struct efi_file_info *info = NULL;
+ struct efi_file_handle *f;
+ static efi_status_t ret;
+ u64 addr;
+ efi_uintn_t bs;
+
+ /* In case of failure nothing is returned */
+ *buffer = NULL;
+ *size = 0;
+
+ /* Open file */
+ f = efi_file_from_path(file_path);
+ if (!f)
+ return EFI_NOT_FOUND;
+
+ /* Get file size */
+ bs = 0;
+ EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+ &bs, info));
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ info = malloc(bs);
+ EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
+ info));
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ /*
+ * When reading the file we do not yet know if it contains an
+ * application, a boottime driver, or a runtime driver. So here we
+ * allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
+ * update the reservation according to the image type.
+ */
+ bs = info->file_size;
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_BOOT_SERVICES_DATA,
+ efi_size_in_pages(bs), &addr);
+ if (ret != EFI_SUCCESS) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+
+ /* Read file */
+ EFI_CALL(ret = f->read(f, &bs, (void *)(uintptr_t)addr));
+ if (ret != EFI_SUCCESS)
+ efi_free_pages(addr, efi_size_in_pages(bs));
+ *buffer = (void *)(uintptr_t)addr;
+ *size = bs;
+error:
+ EFI_CALL(f->close(f));
+ free(info);
+ return ret;
+}
+
+/**
+ * efi_load_image() - load an EFI image into memory
+ * @boot_policy: true for request originating from the boot manager
+ * @parent_image: the caller's image handle
+ * @file_path: the path of the image to load
+ * @source_buffer: memory location from which the image is installed
+ * @source_size: size of the memory area from which the image is installed
+ * @image_handle: handle for the newly installed image
+ *
+ * This function implements the LoadImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_load_image(bool boot_policy,
+ efi_handle_t parent_image,
+ struct efi_device_path *file_path,
+ void *source_buffer,
+ efi_uintn_t source_size,
+ efi_handle_t *image_handle)
+{
+ struct efi_device_path *dp, *fp;
+ struct efi_loaded_image *info = NULL;
+ struct efi_loaded_image_obj **image_obj =
+ (struct efi_loaded_image_obj **)image_handle;
+ efi_status_t ret;
+ void *dest_buffer;
+
+ EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
+ file_path, source_buffer, source_size, image_handle);
+
+ if (!image_handle || (!source_buffer && !file_path) ||
+ !efi_search_obj(parent_image) ||
+ /* The parent image handle must refer to a loaded image */
+ !parent_image->type) {
+ ret = EFI_INVALID_PARAMETER;
+ goto error;
+ }
+
+ if (!source_buffer) {
+ ret = efi_load_image_from_path(file_path, &dest_buffer,
+ &source_size);
+ if (ret != EFI_SUCCESS)
+ goto error;
+ } else {
+ if (!source_size) {
+ ret = EFI_LOAD_ERROR;
+ goto error;
+ }
+ dest_buffer = source_buffer;
+ }
+ /* split file_path which contains both the device and file parts */
+ efi_dp_split_file_path(file_path, &dp, &fp);
+ ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
+ if (ret == EFI_SUCCESS)
+ ret = efi_load_pe(*image_obj, dest_buffer, info);
+ if (!source_buffer)
+ /* Release buffer to which file was loaded */
+ efi_free_pages((uintptr_t)dest_buffer,
+ efi_size_in_pages(source_size));
+ if (ret == EFI_SUCCESS) {
+ info->system_table = &systab;
+ info->parent_handle = parent_image;
+ } else {
+ /* The image is invalid. Release all associated resources. */
+ efi_delete_handle(*image_handle);
+ *image_handle = NULL;
+ free(info);
+ }
+error:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_exit_caches() - fix up caches for EFI payloads if necessary
+ */
+static void efi_exit_caches(void)
+{
+#if defined(CONFIG_EFI_GRUB_ARM32_WORKAROUND)
+ /*
+ * Boooting Linux via GRUB prior to version 2.04 fails on 32bit ARM if
+ * caches are enabled.
+ *
+ * TODO:
+ * According to the UEFI spec caches that can be managed via CP15
+ * operations should be enabled. Caches requiring platform information
+ * to manage should be disabled. This should not happen in
+ * ExitBootServices() but before invoking any UEFI binary is invoked.
+ *
+ * We want to keep the current workaround while GRUB prior to version
+ * 2.04 is still in use.
+ */
+ cleanup_before_linux();
+#endif
+}
+
+/**
+ * efi_exit_boot_services() - stop all boot services
+ * @image_handle: handle of the loaded image
+ * @map_key: key of the memory map
+ *
+ * This function implements the ExitBootServices service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * All timer events are disabled. For exit boot services events the
+ * notification function is called. The boot services are disabled in the
+ * system table.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
+ efi_uintn_t map_key)
+{
+ struct efi_event *evt, *next_event;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %zx", image_handle, map_key);
+
+ /* Check that the caller has read the current memory map */
+ if (map_key != efi_memory_map_key) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Check if ExitBootServices has already been called */
+ if (!systab.boottime)
+ goto out;
+
+ /* Stop all timer related activities */
+ timers_enabled = false;
+
+ /* Add related events to the event group */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->type == EVT_SIGNAL_EXIT_BOOT_SERVICES)
+ evt->group = &efi_guid_event_group_exit_boot_services;
+ }
+ /* Notify that ExitBootServices is invoked. */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group &&
+ !guidcmp(evt->group,
+ &efi_guid_event_group_exit_boot_services)) {
+ efi_signal_event(evt);
+ break;
+ }
+ }
+
+ /* Make sure that notification functions are not called anymore */
+ efi_tpl = TPL_HIGH_LEVEL;
+
+ /* Notify variable services */
+ efi_variables_boot_exit_notify();
+
+ /* Remove all events except EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */
+ list_for_each_entry_safe(evt, next_event, &efi_events, link) {
+ if (evt->type != EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)
+ list_del(&evt->link);
+ }
+
+ board_quiesce_devices();
+
+ /* Patch out unsupported runtime function */
+ efi_runtime_detach();
+
+ /* Fix up caches for EFI payloads if necessary */
+ efi_exit_caches();
+
+ /* This stops all lingering devices */
+ bootm_disable_interrupts();
+
+ /* Disable boot time services */
+ systab.con_in_handle = NULL;
+ systab.con_in = NULL;
+ systab.con_out_handle = NULL;
+ systab.con_out = NULL;
+ systab.stderr_handle = NULL;
+ systab.std_err = NULL;
+ systab.boottime = NULL;
+
+ /* Recalculate CRC32 */
+ efi_update_table_header_crc32(&systab.hdr);
+
+ /* Give the payload some time to boot */
+ efi_set_watchdog(0);
+ WATCHDOG_RESET();
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_get_next_monotonic_count() - get next value of the counter
+ * @count: returned value of the counter
+ *
+ * This function implements the NextMonotonicCount service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
+{
+ static uint64_t mono;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p", count);
+ if (!count) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ *count = mono++;
+ ret = EFI_SUCCESS;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_stall() - sleep
+ * @microseconds: period to sleep in microseconds
+ *
+ * This function implements the Stall service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
+{
+ u64 end_tick;
+
+ EFI_ENTRY("%ld", microseconds);
+
+ end_tick = get_ticks() + usec_to_tick(microseconds);
+ while (get_ticks() < end_tick)
+ efi_timer_check();
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_set_watchdog_timer() - reset the watchdog timer
+ * @timeout: seconds before reset by watchdog
+ * @watchdog_code: code to be logged when resetting
+ * @data_size: size of buffer in bytes
+ * @watchdog_data: buffer with data describing the reset reason
+ *
+ * This function implements the SetWatchdogTimer service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
+ uint64_t watchdog_code,
+ unsigned long data_size,
+ uint16_t *watchdog_data)
+{
+ EFI_ENTRY("%ld, 0x%llx, %ld, %p", timeout, watchdog_code,
+ data_size, watchdog_data);
+ return EFI_EXIT(efi_set_watchdog(timeout));
+}
+
+/**
+ * efi_close_protocol() - close a protocol
+ * @handle: handle on which the protocol shall be closed
+ * @protocol: GUID of the protocol to close
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
+ *
+ * This function implements the CloseProtocol service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
+ const efi_guid_t *protocol,
+ efi_handle_t agent_handle,
+ efi_handle_t controller_handle)
+{
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+ struct efi_open_protocol_info_item *pos;
+ efi_status_t r;
+
+ EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
+ controller_handle);
+
+ if (!efi_search_obj(agent_handle) ||
+ (controller_handle && !efi_search_obj(controller_handle))) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ r = efi_search_protocol(handle, protocol, &handler);
+ if (r != EFI_SUCCESS)
+ goto out;
+
+ r = EFI_NOT_FOUND;
+ list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
+ if (item->info.agent_handle == agent_handle &&
+ item->info.controller_handle == controller_handle) {
+ efi_delete_open_info(item);
+ r = EFI_SUCCESS;
+ }
+ }
+out:
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_open_protocol_information() - provide information about then open status
+ * of a protocol on a handle
+ * @handle: handle for which the information shall be retrieved
+ * @protocol: GUID of the protocol
+ * @entry_buffer: buffer to receive the open protocol information
+ * @entry_count: number of entries available in the buffer
+ *
+ * This function implements the OpenProtocolInformation service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_open_protocol_information(
+ efi_handle_t handle, const efi_guid_t *protocol,
+ struct efi_open_protocol_info_entry **entry_buffer,
+ efi_uintn_t *entry_count)
+{
+ unsigned long buffer_size;
+ unsigned long count;
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+ efi_status_t r;
+
+ EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
+ entry_count);
+
+ /* Check parameters */
+ if (!entry_buffer) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ r = efi_search_protocol(handle, protocol, &handler);
+ if (r != EFI_SUCCESS)
+ goto out;
+
+ /* Count entries */
+ count = 0;
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.open_count)
+ ++count;
+ }
+ *entry_count = count;
+ *entry_buffer = NULL;
+ if (!count) {
+ r = EFI_SUCCESS;
+ goto out;
+ }
+
+ /* Copy entries */
+ buffer_size = count * sizeof(struct efi_open_protocol_info_entry);
+ r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
+ (void **)entry_buffer);
+ if (r != EFI_SUCCESS)
+ goto out;
+ list_for_each_entry_reverse(item, &handler->open_infos, link) {
+ if (item->info.open_count)
+ (*entry_buffer)[--count] = item->info;
+ }
+out:
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_protocols_per_handle() - get protocols installed on a handle
+ * @handle: handle for which the information is retrieved
+ * @protocol_buffer: buffer with protocol GUIDs
+ * @protocol_buffer_count: number of entries in the buffer
+ *
+ * This function implements the ProtocolsPerHandleService.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_protocols_per_handle(
+ efi_handle_t handle, efi_guid_t ***protocol_buffer,
+ efi_uintn_t *protocol_buffer_count)
+{
+ unsigned long buffer_size;
+ struct efi_object *efiobj;
+ struct list_head *protocol_handle;
+ efi_status_t r;
+
+ EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
+ protocol_buffer_count);
+
+ if (!handle || !protocol_buffer || !protocol_buffer_count)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ *protocol_buffer = NULL;
+ *protocol_buffer_count = 0;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* Count protocols */
+ list_for_each(protocol_handle, &efiobj->protocols) {
+ ++*protocol_buffer_count;
+ }
+
+ /* Copy GUIDs */
+ if (*protocol_buffer_count) {
+ size_t j = 0;
+
+ buffer_size = sizeof(efi_guid_t *) * *protocol_buffer_count;
+ r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
+ (void **)protocol_buffer);
+ if (r != EFI_SUCCESS)
+ return EFI_EXIT(r);
+ list_for_each(protocol_handle, &efiobj->protocols) {
+ struct efi_handler *protocol;
+
+ protocol = list_entry(protocol_handle,
+ struct efi_handler, link);
+ (*protocol_buffer)[j] = (void *)protocol->guid;
+ ++j;
+ }
+ }
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_locate_handle_buffer() - locate handles implementing a protocol
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @no_handles: number of returned handles
+ * @buffer: buffer with the returned handles
+ *
+ * This function implements the LocateHandleBuffer service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_locate_handle_buffer(
+ enum efi_locate_search_type search_type,
+ const efi_guid_t *protocol, void *search_key,
+ efi_uintn_t *no_handles, efi_handle_t **buffer)
+{
+ efi_status_t r;
+ efi_uintn_t buffer_size = 0;
+
+ EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
+ no_handles, buffer);
+
+ if (!no_handles || !buffer) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ *no_handles = 0;
+ *buffer = NULL;
+ r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
+ *buffer);
+ if (r != EFI_BUFFER_TOO_SMALL)
+ goto out;
+ r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
+ (void **)buffer);
+ if (r != EFI_SUCCESS)
+ goto out;
+ r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
+ *buffer);
+ if (r == EFI_SUCCESS)
+ *no_handles = buffer_size / sizeof(efi_handle_t);
+out:
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_locate_protocol() - find an interface implementing a protocol
+ * @protocol: GUID of the protocol
+ * @registration: registration key passed to the notification function
+ * @protocol_interface: interface implementing the protocol
+ *
+ * This function implements the LocateProtocol service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
+ void *registration,
+ void **protocol_interface)
+{
+ struct efi_handler *handler;
+ efi_status_t ret;
+ struct efi_object *efiobj;
+
+ EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
+
+ /*
+ * The UEFI spec explicitly requires a protocol even if a registration
+ * key is provided. This differs from the logic in LocateHandle().
+ */
+ if (!protocol || !protocol_interface)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ if (registration) {
+ struct efi_register_notify_event *event;
+ struct efi_protocol_notification *handle;
+
+ event = efi_check_register_notify_event(registration);
+ if (!event)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+ /*
+ * The UEFI spec requires to return EFI_NOT_FOUND if no
+ * protocol instance matches protocol and registration.
+ * So let's do the same for a mismatch between protocol and
+ * registration.
+ */
+ if (guidcmp(&event->protocol, protocol))
+ goto not_found;
+ if (list_empty(&event->handles))
+ goto not_found;
+ handle = list_first_entry(&event->handles,
+ struct efi_protocol_notification,
+ link);
+ efiobj = handle->handle;
+ list_del(&handle->link);
+ free(handle);
+ ret = efi_search_protocol(efiobj, protocol, &handler);
+ if (ret == EFI_SUCCESS)
+ goto found;
+ } else {
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ ret = efi_search_protocol(efiobj, protocol, &handler);
+ if (ret == EFI_SUCCESS)
+ goto found;
+ }
+ }
+not_found:
+ *protocol_interface = NULL;
+ return EFI_EXIT(EFI_NOT_FOUND);
+found:
+ *protocol_interface = handler->protocol_interface;
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_locate_device_path() - Get the device path and handle of an device
+ * implementing a protocol
+ * @protocol: GUID of the protocol
+ * @device_path: device path
+ * @device: handle of the device
+ *
+ * This function implements the LocateDevicePath service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_locate_device_path(
+ const efi_guid_t *protocol,
+ struct efi_device_path **device_path,
+ efi_handle_t *device)
+{
+ struct efi_device_path *dp;
+ size_t i;
+ struct efi_handler *handler;
+ efi_handle_t *handles;
+ size_t len, len_dp;
+ size_t len_best = 0;
+ efi_uintn_t no_handles;
+ u8 *remainder;
+ efi_status_t ret;
+
+ EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
+
+ if (!protocol || !device_path || !*device_path) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Find end of device path */
+ len = efi_dp_instance_size(*device_path);
+
+ /* Get all handles implementing the protocol */
+ ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
+ &no_handles, &handles));
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ for (i = 0; i < no_handles; ++i) {
+ /* Find the device path protocol */
+ ret = efi_search_protocol(handles[i], &efi_guid_device_path,
+ &handler);
+ if (ret != EFI_SUCCESS)
+ continue;
+ dp = (struct efi_device_path *)handler->protocol_interface;
+ len_dp = efi_dp_instance_size(dp);
+ /*
+ * This handle can only be a better fit
+ * if its device path length is longer than the best fit and
+ * if its device path length is shorter of equal the searched
+ * device path.
+ */
+ if (len_dp <= len_best || len_dp > len)
+ continue;
+ /* Check if dp is a subpath of device_path */
+ if (memcmp(*device_path, dp, len_dp))
+ continue;
+ if (!device) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ *device = handles[i];
+ len_best = len_dp;
+ }
+ if (len_best) {
+ remainder = (u8 *)*device_path + len_best;
+ *device_path = (struct efi_device_path *)remainder;
+ ret = EFI_SUCCESS;
+ } else {
+ ret = EFI_NOT_FOUND;
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_install_multiple_protocol_interfaces() - Install multiple protocol
+ * interfaces
+ * @handle: handle on which the protocol interfaces shall be installed
+ * @...: NULL terminated argument list with pairs of protocol GUIDS and
+ * interfaces
+ *
+ * This function implements the MultipleProtocolInterfaces service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_install_multiple_protocol_interfaces
+ (efi_handle_t *handle, ...)
+{
+ EFI_ENTRY("%p", handle);
+
+ efi_va_list argptr;
+ const efi_guid_t *protocol;
+ void *protocol_interface;
+ efi_handle_t old_handle;
+ efi_status_t r = EFI_SUCCESS;
+ int i = 0;
+
+ if (!handle)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ efi_va_start(argptr, handle);
+ for (;;) {
+ protocol = efi_va_arg(argptr, efi_guid_t*);
+ if (!protocol)
+ break;
+ protocol_interface = efi_va_arg(argptr, void*);
+ /* Check that a device path has not been installed before */
+ if (!guidcmp(protocol, &efi_guid_device_path)) {
+ struct efi_device_path *dp = protocol_interface;
+
+ r = EFI_CALL(efi_locate_device_path(protocol, &dp,
+ &old_handle));
+ if (r == EFI_SUCCESS &&
+ dp->type == DEVICE_PATH_TYPE_END) {
+ EFI_PRINT("Path %pD already installed\n",
+ protocol_interface);
+ r = EFI_ALREADY_STARTED;
+ break;
+ }
+ }
+ r = EFI_CALL(efi_install_protocol_interface(
+ handle, protocol,
+ EFI_NATIVE_INTERFACE,
+ protocol_interface));
+ if (r != EFI_SUCCESS)
+ break;
+ i++;
+ }
+ efi_va_end(argptr);
+ if (r == EFI_SUCCESS)
+ return EFI_EXIT(r);
+
+ /* If an error occurred undo all changes. */
+ efi_va_start(argptr, handle);
+ for (; i; --i) {
+ protocol = efi_va_arg(argptr, efi_guid_t*);
+ protocol_interface = efi_va_arg(argptr, void*);
+ EFI_CALL(efi_uninstall_protocol_interface(*handle, protocol,
+ protocol_interface));
+ }
+ efi_va_end(argptr);
+
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_uninstall_multiple_protocol_interfaces() - uninstall multiple protocol
+ * interfaces
+ * @handle: handle from which the protocol interfaces shall be removed
+ * @...: NULL terminated argument list with pairs of protocol GUIDS and
+ * interfaces
+ *
+ * This function implements the UninstallMultipleProtocolInterfaces service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
+ efi_handle_t handle, ...)
+{
+ EFI_ENTRY("%p", handle);
+
+ efi_va_list argptr;
+ const efi_guid_t *protocol;
+ void *protocol_interface;
+ efi_status_t r = EFI_SUCCESS;
+ size_t i = 0;
+
+ if (!handle)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ efi_va_start(argptr, handle);
+ for (;;) {
+ protocol = efi_va_arg(argptr, efi_guid_t*);
+ if (!protocol)
+ break;
+ protocol_interface = efi_va_arg(argptr, void*);
+ r = efi_uninstall_protocol(handle, protocol,
+ protocol_interface);
+ if (r != EFI_SUCCESS)
+ break;
+ i++;
+ }
+ efi_va_end(argptr);
+ if (r == EFI_SUCCESS) {
+ /* If the last protocol has been removed, delete the handle. */
+ if (list_empty(&handle->protocols)) {
+ list_del(&handle->link);
+ free(handle);
+ }
+ return EFI_EXIT(r);
+ }
+
+ /* If an error occurred undo all changes. */
+ efi_va_start(argptr, handle);
+ for (; i; --i) {
+ protocol = efi_va_arg(argptr, efi_guid_t*);
+ protocol_interface = efi_va_arg(argptr, void*);
+ EFI_CALL(efi_install_protocol_interface(&handle, protocol,
+ EFI_NATIVE_INTERFACE,
+ protocol_interface));
+ }
+ efi_va_end(argptr);
+
+ /* In case of an error always return EFI_INVALID_PARAMETER */
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+}
+
+/**
+ * efi_calculate_crc32() - calculate cyclic redundancy code
+ * @data: buffer with data
+ * @data_size: size of buffer in bytes
+ * @crc32_p: cyclic redundancy code
+ *
+ * This function implements the CalculateCrc32 service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_calculate_crc32(const void *data,
+ efi_uintn_t data_size,
+ u32 *crc32_p)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %zu", data, data_size);
+ if (!data || !data_size || !crc32_p) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ *crc32_p = crc32(0, data, data_size);
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_copy_mem() - copy memory
+ * @destination: destination of the copy operation
+ * @source: source of the copy operation
+ * @length: number of bytes to copy
+ *
+ * This function implements the CopyMem service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static void EFIAPI efi_copy_mem(void *destination, const void *source,
+ size_t length)
+{
+ EFI_ENTRY("%p, %p, %ld", destination, source, (unsigned long)length);
+ memmove(destination, source, length);
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_set_mem() - Fill memory with a byte value.
+ * @buffer: buffer to fill
+ * @size: size of buffer in bytes
+ * @value: byte to copy to the buffer
+ *
+ * This function implements the SetMem service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value)
+{
+ EFI_ENTRY("%p, %ld, 0x%x", buffer, (unsigned long)size, value);
+ memset(buffer, value, size);
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_protocol_open() - open protocol interface on a handle
+ * @handler: handler of a protocol
+ * @protocol_interface: interface implementing the protocol
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
+ * @attributes: attributes indicating how to open the protocol
+ *
+ * Return: status code
+ */
+static efi_status_t efi_protocol_open(
+ struct efi_handler *handler,
+ void **protocol_interface, void *agent_handle,
+ void *controller_handle, uint32_t attributes)
+{
+ struct efi_open_protocol_info_item *item;
+ struct efi_open_protocol_info_entry *match = NULL;
+ bool opened_by_driver = false;
+ bool opened_exclusive = false;
+
+ /* If there is no agent, only return the interface */
+ if (!agent_handle)
+ goto out;
+
+ /* For TEST_PROTOCOL ignore interface attribute */
+ if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+ *protocol_interface = NULL;
+
+ /*
+ * Check if the protocol is already opened by a driver with the same
+ * attributes or opened exclusively
+ */
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.agent_handle == agent_handle) {
+ if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) &&
+ (item->info.attributes == attributes))
+ return EFI_ALREADY_STARTED;
+ } else {
+ if (item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_DRIVER)
+ opened_by_driver = true;
+ }
+ if (item->info.attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE)
+ opened_exclusive = true;
+ }
+
+ /* Only one controller can open the protocol exclusively */
+ if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+ if (opened_exclusive)
+ return EFI_ACCESS_DENIED;
+ } else if (attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ if (opened_exclusive || opened_by_driver)
+ return EFI_ACCESS_DENIED;
+ }
+
+ /* Prepare exclusive opening */
+ if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+ /* Try to disconnect controllers */
+disconnect_next:
+ opened_by_driver = false;
+ list_for_each_entry(item, &handler->open_infos, link) {
+ efi_status_t ret;
+
+ if (item->info.attributes ==
+ EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ ret = EFI_CALL(efi_disconnect_controller(
+ item->info.controller_handle,
+ item->info.agent_handle,
+ NULL));
+ if (ret == EFI_SUCCESS)
+ /*
+ * Child controllers may have been
+ * removed from the open_infos list. So
+ * let's restart the loop.
+ */
+ goto disconnect_next;
+ else
+ opened_by_driver = true;
+ }
+ }
+ /* Only one driver can be connected */
+ if (opened_by_driver)
+ return EFI_ACCESS_DENIED;
+ }
+
+ /* Find existing entry */
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.agent_handle == agent_handle &&
+ item->info.controller_handle == controller_handle &&
+ item->info.attributes == attributes)
+ match = &item->info;
+ }
+ /* None found, create one */
+ if (!match) {
+ match = efi_create_open_info(handler);
+ if (!match)
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ match->agent_handle = agent_handle;
+ match->controller_handle = controller_handle;
+ match->attributes = attributes;
+ match->open_count++;
+
+out:
+ /* For TEST_PROTOCOL ignore interface attribute. */
+ if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+ *protocol_interface = handler->protocol_interface;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_open_protocol() - open protocol interface on a handle
+ * @handle: handle on which the protocol shall be opened
+ * @protocol: GUID of the protocol
+ * @protocol_interface: interface implementing the protocol
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
+ * @attributes: attributes indicating how to open the protocol
+ *
+ * This function implements the OpenProtocol interface.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_open_protocol
+ (efi_handle_t handle, const efi_guid_t *protocol,
+ void **protocol_interface, efi_handle_t agent_handle,
+ efi_handle_t controller_handle, uint32_t attributes)
+{
+ struct efi_handler *handler;
+ efi_status_t r = EFI_INVALID_PARAMETER;
+
+ EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
+ protocol_interface, agent_handle, controller_handle,
+ attributes);
+
+ if (!handle || !protocol ||
+ (!protocol_interface && attributes !=
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
+ goto out;
+ }
+
+ switch (attributes) {
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
+ break;
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
+ if (controller_handle == handle)
+ goto out;
+ /* fall-through */
+ case EFI_OPEN_PROTOCOL_BY_DRIVER:
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ /* Check that the controller handle is valid */
+ if (!efi_search_obj(controller_handle))
+ goto out;
+ /* fall-through */
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ /* Check that the agent handle is valid */
+ if (!efi_search_obj(agent_handle))
+ goto out;
+ break;
+ default:
+ goto out;
+ }
+
+ r = efi_search_protocol(handle, protocol, &handler);
+ switch (r) {
+ case EFI_SUCCESS:
+ break;
+ case EFI_NOT_FOUND:
+ r = EFI_UNSUPPORTED;
+ goto out;
+ default:
+ goto out;
+ }
+
+ r = efi_protocol_open(handler, protocol_interface, agent_handle,
+ controller_handle, attributes);
+out:
+ return EFI_EXIT(r);
+}
+
+/**
+ * efi_start_image() - call the entry point of an image
+ * @image_handle: handle of the image
+ * @exit_data_size: size of the buffer
+ * @exit_data: buffer to receive the exit data of the called image
+ *
+ * This function implements the StartImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
+ efi_uintn_t *exit_data_size,
+ u16 **exit_data)
+{
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
+ efi_status_t ret;
+ void *info;
+ efi_handle_t parent_image = current_image;
+
+ EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
+
+ /* Check parameters */
+ if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
+ &info, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (ret != EFI_SUCCESS)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ image_obj->exit_data_size = exit_data_size;
+ image_obj->exit_data = exit_data;
+
+ /* call the image! */
+ if (setjmp(&image_obj->exit_jmp)) {
+ /*
+ * We called the entry point of the child image with EFI_CALL
+ * in the lines below. The child image called the Exit() boot
+ * service efi_exit() which executed the long jump that brought
+ * us to the current line. This implies that the second half
+ * of the EFI_CALL macro has not been executed.
+ */
+#ifdef CONFIG_ARM
+ /*
+ * efi_exit() called efi_restore_gd(). We have to undo this
+ * otherwise __efi_entry_check() will put the wrong value into
+ * app_gd.
+ */
+ gd = app_gd;
+#endif
+ /*
+ * To get ready to call EFI_EXIT below we have to execute the
+ * missed out steps of EFI_CALL.
+ */
+ assert(__efi_entry_check());
+ EFI_PRINT("%lu returned by started image\n",
+ (unsigned long)((uintptr_t)image_obj->exit_status &
+ ~EFI_ERROR_MASK));
+ current_image = parent_image;
+ return EFI_EXIT(image_obj->exit_status);
+ }
+
+ current_image = image_handle;
+ image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
+ EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
+ ret = EFI_CALL(image_obj->entry(image_handle, &systab));
+
+ /*
+ * Usually UEFI applications call Exit() instead of returning.
+ * But because the world doesn't consist of ponies and unicorns,
+ * we're happy to emulate that behavior on behalf of a payload
+ * that forgot.
+ */
+ return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
+}
+
+/**
+ * efi_delete_image() - delete loaded image from memory)
+ *
+ * @image_obj: handle of the loaded image
+ * @loaded_image_protocol: loaded image protocol
+ */
+static efi_status_t efi_delete_image
+ (struct efi_loaded_image_obj *image_obj,
+ struct efi_loaded_image *loaded_image_protocol)
+{
+ struct efi_object *efiobj;
+ efi_status_t r, ret = EFI_SUCCESS;
+
+close_next:
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ struct efi_handler *protocol;
+
+ list_for_each_entry(protocol, &efiobj->protocols, link) {
+ struct efi_open_protocol_info_item *info;
+
+ list_for_each_entry(info, &protocol->open_infos, link) {
+ if (info->info.agent_handle !=
+ (efi_handle_t)image_obj)
+ continue;
+ r = EFI_CALL(efi_close_protocol
+ (efiobj, protocol->guid,
+ info->info.agent_handle,
+ info->info.controller_handle
+ ));
+ if (r != EFI_SUCCESS)
+ ret = r;
+ /*
+ * Closing protocols may results in further
+ * items being deleted. To play it safe loop
+ * over all elements again.
+ */
+ goto close_next;
+ }
+ }
+ }
+
+ efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
+ efi_size_in_pages(loaded_image_protocol->image_size));
+ efi_delete_handle(&image_obj->header);
+
+ return ret;
+}
+
+/**
+ * efi_unload_image() - unload an EFI image
+ * @image_handle: handle of the image to be unloaded
+ *
+ * This function implements the UnloadImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct efi_object *efiobj;
+ struct efi_loaded_image *loaded_image_protocol;
+
+ EFI_ENTRY("%p", image_handle);
+
+ efiobj = efi_search_obj(image_handle);
+ if (!efiobj) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /* Find the loaded image protocol */
+ ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
+ (void **)&loaded_image_protocol,
+ NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (ret != EFI_SUCCESS) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ switch (efiobj->type) {
+ case EFI_OBJECT_TYPE_STARTED_IMAGE:
+ /* Call the unload function */
+ if (!loaded_image_protocol->unload) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ ret = EFI_CALL(loaded_image_protocol->unload(image_handle));
+ if (ret != EFI_SUCCESS)
+ goto out;
+ break;
+ case EFI_OBJECT_TYPE_LOADED_IMAGE:
+ break;
+ default:
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ efi_delete_image((struct efi_loaded_image_obj *)efiobj,
+ loaded_image_protocol);
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_update_exit_data() - fill exit data parameters of StartImage()
+ *
+ * @image_obj: image handle
+ * @exit_data_size: size of the exit data buffer
+ * @exit_data: buffer with data returned by UEFI payload
+ * Return: status code
+ */
+static efi_status_t efi_update_exit_data(struct efi_loaded_image_obj *image_obj,
+ efi_uintn_t exit_data_size,
+ u16 *exit_data)
+{
+ efi_status_t ret;
+
+ /*
+ * If exit_data is not provided to StartImage(), exit_data_size must be
+ * ignored.
+ */
+ if (!image_obj->exit_data)
+ return EFI_SUCCESS;
+ if (image_obj->exit_data_size)
+ *image_obj->exit_data_size = exit_data_size;
+ if (exit_data_size && exit_data) {
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
+ exit_data_size,
+ (void **)image_obj->exit_data);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ memcpy(*image_obj->exit_data, exit_data, exit_data_size);
+ } else {
+ image_obj->exit_data = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_exit() - leave an EFI application or driver
+ * @image_handle: handle of the application or driver that is exiting
+ * @exit_status: status code
+ * @exit_data_size: size of the buffer in bytes
+ * @exit_data: buffer with data describing an error
+ *
+ * This function implements the Exit service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
+ efi_status_t exit_status,
+ efi_uintn_t exit_data_size,
+ u16 *exit_data)
+{
+ /*
+ * TODO: We should call the unload procedure of the loaded
+ * image protocol.
+ */
+ efi_status_t ret;
+ struct efi_loaded_image *loaded_image_protocol;
+ struct efi_loaded_image_obj *image_obj =
+ (struct efi_loaded_image_obj *)image_handle;
+
+ EFI_ENTRY("%p, %ld, %zu, %p", image_handle, exit_status,
+ exit_data_size, exit_data);
+
+ /* Check parameters */
+ ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
+ (void **)&loaded_image_protocol,
+ NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (ret != EFI_SUCCESS) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Unloading of unstarted images */
+ switch (image_obj->header.type) {
+ case EFI_OBJECT_TYPE_STARTED_IMAGE:
+ break;
+ case EFI_OBJECT_TYPE_LOADED_IMAGE:
+ efi_delete_image(image_obj, loaded_image_protocol);
+ ret = EFI_SUCCESS;
+ goto out;
+ default:
+ /* Handle does not refer to loaded image */
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /* A started image can only be unloaded it is the last one started. */
+ if (image_handle != current_image) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Exit data is only foreseen in case of failure. */
+ if (exit_status != EFI_SUCCESS) {
+ ret = efi_update_exit_data(image_obj, exit_data_size,
+ exit_data);
+ /* Exiting has priority. Don't return error to caller. */
+ if (ret != EFI_SUCCESS)
+ EFI_PRINT("%s: out of memory\n", __func__);
+ }
+ if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION ||
+ exit_status != EFI_SUCCESS)
+ efi_delete_image(image_obj, loaded_image_protocol);
+
+ /* Make sure entry/exit counts for EFI world cross-overs match */
+ EFI_EXIT(exit_status);
+
+ /*
+ * But longjmp out with the U-Boot gd, not the application's, as
+ * the other end is a setjmp call inside EFI context.
+ */
+ efi_restore_gd();
+
+ image_obj->exit_status = exit_status;
+ longjmp(&image_obj->exit_jmp, 1);
+
+ panic("EFI application exited");
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_handle_protocol() - get interface of a protocol on a handle
+ * @handle: handle on which the protocol shall be opened
+ * @protocol: GUID of the protocol
+ * @protocol_interface: interface implementing the protocol
+ *
+ * This function implements the HandleProtocol service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle,
+ const efi_guid_t *protocol,
+ void **protocol_interface)
+{
+ return efi_open_protocol(handle, protocol, protocol_interface, efi_root,
+ NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
+}
+
+/**
+ * efi_bind_controller() - bind a single driver to a controller
+ * @controller_handle: controller handle
+ * @driver_image_handle: driver handle
+ * @remain_device_path: remaining path
+ *
+ * Return: status code
+ */
+static efi_status_t efi_bind_controller(
+ efi_handle_t controller_handle,
+ efi_handle_t driver_image_handle,
+ struct efi_device_path *remain_device_path)
+{
+ struct efi_driver_binding_protocol *binding_protocol;
+ efi_status_t r;
+
+ r = EFI_CALL(efi_open_protocol(driver_image_handle,
+ &efi_guid_driver_binding_protocol,
+ (void **)&binding_protocol,
+ driver_image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (r != EFI_SUCCESS)
+ return r;
+ r = EFI_CALL(binding_protocol->supported(binding_protocol,
+ controller_handle,
+ remain_device_path));
+ if (r == EFI_SUCCESS)
+ r = EFI_CALL(binding_protocol->start(binding_protocol,
+ controller_handle,
+ remain_device_path));
+ EFI_CALL(efi_close_protocol(driver_image_handle,
+ &efi_guid_driver_binding_protocol,
+ driver_image_handle, NULL));
+ return r;
+}
+
+/**
+ * efi_connect_single_controller() - connect a single driver to a controller
+ * @controller_handle: controller
+ * @driver_image_handle: driver
+ * @remain_device_path: remaining path
+ *
+ * Return: status code
+ */
+static efi_status_t efi_connect_single_controller(
+ efi_handle_t controller_handle,
+ efi_handle_t *driver_image_handle,
+ struct efi_device_path *remain_device_path)
+{
+ efi_handle_t *buffer;
+ size_t count;
+ size_t i;
+ efi_status_t r;
+ size_t connected = 0;
+
+ /* Get buffer with all handles with driver binding protocol */
+ r = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
+ &efi_guid_driver_binding_protocol,
+ NULL, &count, &buffer));
+ if (r != EFI_SUCCESS)
+ return r;
+
+ /* Context Override */
+ if (driver_image_handle) {
+ for (; *driver_image_handle; ++driver_image_handle) {
+ for (i = 0; i < count; ++i) {
+ if (buffer[i] == *driver_image_handle) {
+ buffer[i] = NULL;
+ r = efi_bind_controller(
+ controller_handle,
+ *driver_image_handle,
+ remain_device_path);
+ /*
+ * For drivers that do not support the
+ * controller or are already connected
+ * we receive an error code here.
+ */
+ if (r == EFI_SUCCESS)
+ ++connected;
+ }
+ }
+ }
+ }
+
+ /*
+ * TODO: Some overrides are not yet implemented:
+ * - Platform Driver Override
+ * - Driver Family Override Search
+ * - Bus Specific Driver Override
+ */
+
+ /* Driver Binding Search */
+ for (i = 0; i < count; ++i) {
+ if (buffer[i]) {
+ r = efi_bind_controller(controller_handle,
+ buffer[i],
+ remain_device_path);
+ if (r == EFI_SUCCESS)
+ ++connected;
+ }
+ }
+
+ efi_free_pool(buffer);
+ if (!connected)
+ return EFI_NOT_FOUND;
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_connect_controller() - connect a controller to a driver
+ * @controller_handle: handle of the controller
+ * @driver_image_handle: handle of the driver
+ * @remain_device_path: device path of a child controller
+ * @recursive: true to connect all child controllers
+ *
+ * This function implements the ConnectController service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * First all driver binding protocol handles are tried for binding drivers.
+ * Afterwards all handles that have opened a protocol of the controller
+ * with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER are connected to drivers.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_connect_controller(
+ efi_handle_t controller_handle,
+ efi_handle_t *driver_image_handle,
+ struct efi_device_path *remain_device_path,
+ bool recursive)
+{
+ efi_status_t r;
+ efi_status_t ret = EFI_NOT_FOUND;
+ struct efi_object *efiobj;
+
+ EFI_ENTRY("%p, %p, %pD, %d", controller_handle, driver_image_handle,
+ remain_device_path, recursive);
+
+ efiobj = efi_search_obj(controller_handle);
+ if (!efiobj) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ r = efi_connect_single_controller(controller_handle,
+ driver_image_handle,
+ remain_device_path);
+ if (r == EFI_SUCCESS)
+ ret = EFI_SUCCESS;
+ if (recursive) {
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+
+ list_for_each_entry(handler, &efiobj->protocols, link) {
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ r = EFI_CALL(efi_connect_controller(
+ item->info.controller_handle,
+ driver_image_handle,
+ remain_device_path,
+ recursive));
+ if (r == EFI_SUCCESS)
+ ret = EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ /* Check for child controller specified by end node */
+ if (ret != EFI_SUCCESS && remain_device_path &&
+ remain_device_path->type == DEVICE_PATH_TYPE_END)
+ ret = EFI_SUCCESS;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_reinstall_protocol_interface() - reinstall protocol interface
+ * @handle: handle on which the protocol shall be reinstalled
+ * @protocol: GUID of the protocol to be installed
+ * @old_interface: interface to be removed
+ * @new_interface: interface to be installed
+ *
+ * This function implements the ReinstallProtocolInterface service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * The old interface is uninstalled. The new interface is installed.
+ * Drivers are connected.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_reinstall_protocol_interface(
+ efi_handle_t handle, const efi_guid_t *protocol,
+ void *old_interface, void *new_interface)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
+ new_interface);
+
+ /* Uninstall protocol but do not delete handle */
+ ret = efi_uninstall_protocol(handle, protocol, old_interface);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Install the new protocol */
+ ret = efi_add_protocol(handle, protocol, new_interface);
+ /*
+ * The UEFI spec does not specify what should happen to the handle
+ * if in case of an error no protocol interface remains on the handle.
+ * So let's do nothing here.
+ */
+ if (ret != EFI_SUCCESS)
+ goto out;
+ /*
+ * The returned status code has to be ignored.
+ * Do not create an error if no suitable driver for the handle exists.
+ */
+ EFI_CALL(efi_connect_controller(handle, NULL, NULL, true));
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_get_child_controllers() - get all child controllers associated to a driver
+ * @efiobj: handle of the controller
+ * @driver_handle: handle of the driver
+ * @number_of_children: number of child controllers
+ * @child_handle_buffer: handles of the the child controllers
+ *
+ * The allocated buffer has to be freed with free().
+ *
+ * Return: status code
+ */
+static efi_status_t efi_get_child_controllers(
+ struct efi_object *efiobj,
+ efi_handle_t driver_handle,
+ efi_uintn_t *number_of_children,
+ efi_handle_t **child_handle_buffer)
+{
+ struct efi_handler *handler;
+ struct efi_open_protocol_info_item *item;
+ efi_uintn_t count = 0, i;
+ bool duplicate;
+
+ /* Count all child controller associations */
+ list_for_each_entry(handler, &efiobj->protocols, link) {
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.agent_handle == driver_handle &&
+ item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
+ ++count;
+ }
+ }
+ /*
+ * Create buffer. In case of duplicate child controller assignments
+ * the buffer will be too large. But that does not harm.
+ */
+ *number_of_children = 0;
+ *child_handle_buffer = calloc(count, sizeof(efi_handle_t));
+ if (!*child_handle_buffer)
+ return EFI_OUT_OF_RESOURCES;
+ /* Copy unique child handles */
+ list_for_each_entry(handler, &efiobj->protocols, link) {
+ list_for_each_entry(item, &handler->open_infos, link) {
+ if (item->info.agent_handle == driver_handle &&
+ item->info.attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ /* Check this is a new child controller */
+ duplicate = false;
+ for (i = 0; i < *number_of_children; ++i) {
+ if ((*child_handle_buffer)[i] ==
+ item->info.controller_handle)
+ duplicate = true;
+ }
+ /* Copy handle to buffer */
+ if (!duplicate) {
+ i = (*number_of_children)++;
+ (*child_handle_buffer)[i] =
+ item->info.controller_handle;
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_disconnect_controller() - disconnect a controller from a driver
+ * @controller_handle: handle of the controller
+ * @driver_image_handle: handle of the driver
+ * @child_handle: handle of the child to destroy
+ *
+ * This function implements the DisconnectController service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_disconnect_controller(
+ efi_handle_t controller_handle,
+ efi_handle_t driver_image_handle,
+ efi_handle_t child_handle)
+{
+ struct efi_driver_binding_protocol *binding_protocol;
+ efi_handle_t *child_handle_buffer = NULL;
+ size_t number_of_children = 0;
+ efi_status_t r;
+ struct efi_object *efiobj;
+
+ EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
+ child_handle);
+
+ efiobj = efi_search_obj(controller_handle);
+ if (!efiobj) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (child_handle && !efi_search_obj(child_handle)) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* If no driver handle is supplied, disconnect all drivers */
+ if (!driver_image_handle) {
+ r = efi_disconnect_all_drivers(efiobj, NULL, child_handle);
+ goto out;
+ }
+
+ /* Create list of child handles */
+ if (child_handle) {
+ number_of_children = 1;
+ child_handle_buffer = &child_handle;
+ } else {
+ efi_get_child_controllers(efiobj,
+ driver_image_handle,
+ &number_of_children,
+ &child_handle_buffer);
+ }
+
+ /* Get the driver binding protocol */
+ r = EFI_CALL(efi_open_protocol(driver_image_handle,
+ &efi_guid_driver_binding_protocol,
+ (void **)&binding_protocol,
+ driver_image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+ if (r != EFI_SUCCESS) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /* Remove the children */
+ if (number_of_children) {
+ r = EFI_CALL(binding_protocol->stop(binding_protocol,
+ controller_handle,
+ number_of_children,
+ child_handle_buffer));
+ if (r != EFI_SUCCESS) {
+ r = EFI_DEVICE_ERROR;
+ goto out;
+ }
+ }
+ /* Remove the driver */
+ if (!child_handle) {
+ r = EFI_CALL(binding_protocol->stop(binding_protocol,
+ controller_handle,
+ 0, NULL));
+ if (r != EFI_SUCCESS) {
+ r = EFI_DEVICE_ERROR;
+ goto out;
+ }
+ }
+ EFI_CALL(efi_close_protocol(driver_image_handle,
+ &efi_guid_driver_binding_protocol,
+ driver_image_handle, NULL));
+ r = EFI_SUCCESS;
+out:
+ if (!child_handle)
+ free(child_handle_buffer);
+ return EFI_EXIT(r);
+}
+
+static struct efi_boot_services efi_boot_services = {
+ .hdr = {
+ .signature = EFI_BOOT_SERVICES_SIGNATURE,
+ .revision = EFI_SPECIFICATION_VERSION,
+ .headersize = sizeof(struct efi_boot_services),
+ },
+ .raise_tpl = efi_raise_tpl,
+ .restore_tpl = efi_restore_tpl,
+ .allocate_pages = efi_allocate_pages_ext,
+ .free_pages = efi_free_pages_ext,
+ .get_memory_map = efi_get_memory_map_ext,
+ .allocate_pool = efi_allocate_pool_ext,
+ .free_pool = efi_free_pool_ext,
+ .create_event = efi_create_event_ext,
+ .set_timer = efi_set_timer_ext,
+ .wait_for_event = efi_wait_for_event,
+ .signal_event = efi_signal_event_ext,
+ .close_event = efi_close_event,
+ .check_event = efi_check_event,
+ .install_protocol_interface = efi_install_protocol_interface,
+ .reinstall_protocol_interface = efi_reinstall_protocol_interface,
+ .uninstall_protocol_interface = efi_uninstall_protocol_interface,
+ .handle_protocol = efi_handle_protocol,
+ .reserved = NULL,
+ .register_protocol_notify = efi_register_protocol_notify,
+ .locate_handle = efi_locate_handle_ext,
+ .locate_device_path = efi_locate_device_path,
+ .install_configuration_table = efi_install_configuration_table_ext,
+ .load_image = efi_load_image,
+ .start_image = efi_start_image,
+ .exit = efi_exit,
+ .unload_image = efi_unload_image,
+ .exit_boot_services = efi_exit_boot_services,
+ .get_next_monotonic_count = efi_get_next_monotonic_count,
+ .stall = efi_stall,
+ .set_watchdog_timer = efi_set_watchdog_timer,
+ .connect_controller = efi_connect_controller,
+ .disconnect_controller = efi_disconnect_controller,
+ .open_protocol = efi_open_protocol,
+ .close_protocol = efi_close_protocol,
+ .open_protocol_information = efi_open_protocol_information,
+ .protocols_per_handle = efi_protocols_per_handle,
+ .locate_handle_buffer = efi_locate_handle_buffer,
+ .locate_protocol = efi_locate_protocol,
+ .install_multiple_protocol_interfaces =
+ efi_install_multiple_protocol_interfaces,
+ .uninstall_multiple_protocol_interfaces =
+ efi_uninstall_multiple_protocol_interfaces,
+ .calculate_crc32 = efi_calculate_crc32,
+ .copy_mem = efi_copy_mem,
+ .set_mem = efi_set_mem,
+ .create_event_ex = efi_create_event_ex,
+};
+
+static u16 __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
+
+struct efi_system_table __efi_runtime_data systab = {
+ .hdr = {
+ .signature = EFI_SYSTEM_TABLE_SIGNATURE,
+ .revision = EFI_SPECIFICATION_VERSION,
+ .headersize = sizeof(struct efi_system_table),
+ },
+ .fw_vendor = firmware_vendor,
+ .fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8,
+ .runtime = &efi_runtime_services,
+ .nr_tables = 0,
+ .tables = NULL,
+};
+
+/**
+ * efi_initialize_system_table() - Initialize system table
+ *
+ * Return: status code
+ */
+efi_status_t efi_initialize_system_table(void)
+{
+ efi_status_t ret;
+
+ /* Allocate configuration table array */
+ ret = efi_allocate_pool(EFI_RUNTIME_SERVICES_DATA,
+ EFI_MAX_CONFIGURATION_TABLES *
+ sizeof(struct efi_configuration_table),
+ (void **)&systab.tables);
+
+ /*
+ * These entries will be set to NULL in ExitBootServices(). To avoid
+ * relocation in SetVirtualAddressMap(), set them dynamically.
+ */
+ systab.con_in = &efi_con_in;
+ systab.con_out = &efi_con_out;
+ systab.std_err = &efi_con_out;
+ systab.boottime = &efi_boot_services;
+
+ /* Set CRC32 field in table headers */
+ efi_update_table_header_crc32(&systab.hdr);
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
+ efi_update_table_header_crc32(&efi_boot_services.hdr);
+
+ return ret;
+}
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
new file mode 100644
index 00000000..218f7caa
--- /dev/null
+++ b/lib/efi_loader/efi_console.c
@@ -0,0 +1,1158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application console interface
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <time.h>
+#include <dm/device.h>
+#include <efi_loader.h>
+#include <env.h>
+#include <stdio_dev.h>
+#include <video_console.h>
+
+#define EFI_COUT_MODE_2 2
+#define EFI_MAX_COUT_MODE 3
+
+struct cout_mode {
+ unsigned long columns;
+ unsigned long rows;
+ int present;
+};
+
+static struct cout_mode efi_cout_modes[] = {
+ /* EFI Mode 0 is 80x25 and always present */
+ {
+ .columns = 80,
+ .rows = 25,
+ .present = 1,
+ },
+ /* EFI Mode 1 is always 80x50 */
+ {
+ .columns = 80,
+ .rows = 50,
+ .present = 0,
+ },
+ /* Value are unknown until we query the console */
+ {
+ .columns = 0,
+ .rows = 0,
+ .present = 0,
+ },
+};
+
+const efi_guid_t efi_guid_text_input_ex_protocol =
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
+const efi_guid_t efi_guid_text_input_protocol =
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
+const efi_guid_t efi_guid_text_output_protocol =
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
+
+#define cESC '\x1b'
+#define ESC "\x1b"
+
+/* Default to mode 0 */
+static struct simple_text_output_mode efi_con_mode = {
+ .max_mode = 1,
+ .mode = 0,
+ .attribute = 0,
+ .cursor_column = 0,
+ .cursor_row = 0,
+ .cursor_visible = 1,
+};
+
+static int term_get_char(s32 *c)
+{
+ u64 timeout;
+
+ /* Wait up to 100 ms for a character */
+ timeout = timer_get_us() + 100000;
+
+ while (!tstc())
+ if (timer_get_us() > timeout)
+ return 1;
+
+ *c = getc();
+ return 0;
+}
+
+/*
+ * Receive and parse a reply from the terminal.
+ *
+ * @n: array of return values
+ * @num: number of return values expected
+ * @end_char: character indicating end of terminal message
+ * @return: non-zero indicates error
+ */
+static int term_read_reply(int *n, int num, char end_char)
+{
+ s32 c;
+ int i = 0;
+
+ if (term_get_char(&c) || c != cESC)
+ return -1;
+
+ if (term_get_char(&c) || c != '[')
+ return -1;
+
+ n[0] = 0;
+ while (1) {
+ if (!term_get_char(&c)) {
+ if (c == ';') {
+ i++;
+ if (i >= num)
+ return -1;
+ n[i] = 0;
+ continue;
+ } else if (c == end_char) {
+ break;
+ } else if (c > '9' || c < '0') {
+ return -1;
+ }
+
+ /* Read one more decimal position */
+ n[i] *= 10;
+ n[i] += c - '0';
+ } else {
+ return -1;
+ }
+ }
+ if (i != num - 1)
+ return -1;
+
+ return 0;
+}
+
+static efi_status_t EFIAPI efi_cout_output_string(
+ struct efi_simple_text_output_protocol *this,
+ const efi_string_t string)
+{
+ struct simple_text_output_mode *con = &efi_con_mode;
+ struct cout_mode *mode = &efi_cout_modes[con->mode];
+ char *buf, *pos;
+ u16 *p;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p", this, string);
+
+ if (!this || !string) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ buf = malloc(utf16_utf8_strlen(string) + 1);
+ if (!buf) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ pos = buf;
+ utf16_utf8_strcpy(&pos, string);
+ fputs(stdout, buf);
+ free(buf);
+
+ /*
+ * Update the cursor position.
+ *
+ * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
+ * and U000D. All other control characters are ignored. Any non-control
+ * character increase the column by one.
+ */
+ for (p = string; *p; ++p) {
+ switch (*p) {
+ case '\b': /* U+0008, backspace */
+ if (con->cursor_column)
+ con->cursor_column--;
+ break;
+ case '\n': /* U+000A, newline */
+ con->cursor_column = 0;
+ con->cursor_row++;
+ break;
+ case '\r': /* U+000D, carriage-return */
+ con->cursor_column = 0;
+ break;
+ case 0xd800 ... 0xdbff:
+ /*
+ * Ignore high surrogates, we do not want to count a
+ * Unicode character twice.
+ */
+ break;
+ default:
+ /* Exclude control codes */
+ if (*p > 0x1f)
+ con->cursor_column++;
+ break;
+ }
+ if (con->cursor_column >= mode->columns) {
+ con->cursor_column = 0;
+ con->cursor_row++;
+ }
+ /*
+ * When we exceed the row count the terminal will scroll up one
+ * line. We have to adjust the cursor position.
+ */
+ if (con->cursor_row >= mode->rows && con->cursor_row)
+ con->cursor_row--;
+ }
+
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_cout_test_string(
+ struct efi_simple_text_output_protocol *this,
+ const efi_string_t string)
+{
+ EFI_ENTRY("%p, %p", this, string);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
+{
+ if (!mode->present)
+ return false;
+
+ return (mode->rows == rows) && (mode->columns == cols);
+}
+
+/**
+ * query_console_serial() - query console size
+ *
+ * @rows: pointer to return number of rows
+ * @cols: pointer to return number of columns
+ * Returns: 0 on success
+ */
+static int query_console_serial(int *rows, int *cols)
+{
+ int ret = 0;
+ int n[2];
+
+ /* Empty input buffer */
+ while (tstc())
+ getc();
+
+ /*
+ * Not all terminals understand CSI [18t for querying the console size.
+ * We should adhere to escape sequences documented in the console_codes
+ * man page and the ECMA-48 standard.
+ *
+ * So here we follow a different approach. We position the cursor to the
+ * bottom right and query its position. Before leaving the function we
+ * restore the original cursor position.
+ */
+ printf(ESC "7" /* Save cursor position */
+ ESC "[r" /* Set scrolling region to full window */
+ ESC "[999;999H" /* Move to bottom right corner */
+ ESC "[6n"); /* Query cursor position */
+
+ /* Read {rows,cols} */
+ if (term_read_reply(n, 2, 'R')) {
+ ret = 1;
+ goto out;
+ }
+
+ *cols = n[1];
+ *rows = n[0];
+out:
+ printf(ESC "8"); /* Restore cursor position */
+ return ret;
+}
+
+/*
+ * Update the mode table.
+ *
+ * By default the only mode available is 80x25. If the console has at least 50
+ * lines, enable mode 80x50. If we can query the console size and it is neither
+ * 80x25 nor 80x50, set it as an additional mode.
+ */
+static void query_console_size(void)
+{
+ const char *stdout_name = env_get("stdout");
+ int rows = 25, cols = 80;
+
+ if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
+ IS_ENABLED(CONFIG_DM_VIDEO)) {
+ struct stdio_dev *stdout_dev =
+ stdio_get_by_name("vidconsole");
+ struct udevice *dev = stdout_dev->priv;
+ struct vidconsole_priv *priv =
+ dev_get_uclass_priv(dev);
+ rows = priv->rows;
+ cols = priv->cols;
+ } else if (query_console_serial(&rows, &cols)) {
+ return;
+ }
+
+ /* Test if we can have Mode 1 */
+ if (cols >= 80 && rows >= 50) {
+ efi_cout_modes[1].present = 1;
+ efi_con_mode.max_mode = 2;
+ }
+
+ /*
+ * Install our mode as mode 2 if it is different
+ * than mode 0 or 1 and set it as the currently selected mode
+ */
+ if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
+ !cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
+ efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
+ efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
+ efi_cout_modes[EFI_COUT_MODE_2].present = 1;
+ efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
+ efi_con_mode.mode = EFI_COUT_MODE_2;
+ }
+}
+
+static efi_status_t EFIAPI efi_cout_query_mode(
+ struct efi_simple_text_output_protocol *this,
+ unsigned long mode_number, unsigned long *columns,
+ unsigned long *rows)
+{
+ EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
+
+ if (mode_number >= efi_con_mode.max_mode)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+
+ if (efi_cout_modes[mode_number].present != 1)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+
+ if (columns)
+ *columns = efi_cout_modes[mode_number].columns;
+ if (rows)
+ *rows = efi_cout_modes[mode_number].rows;
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct {
+ unsigned int fg;
+ unsigned int bg;
+} color[] = {
+ { 30, 40 }, /* 0: black */
+ { 34, 44 }, /* 1: blue */
+ { 32, 42 }, /* 2: green */
+ { 36, 46 }, /* 3: cyan */
+ { 31, 41 }, /* 4: red */
+ { 35, 45 }, /* 5: magenta */
+ { 33, 43 }, /* 6: brown, map to yellow as EDK2 does*/
+ { 37, 47 }, /* 7: light gray, map to white */
+};
+
+/* See EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). */
+static efi_status_t EFIAPI efi_cout_set_attribute(
+ struct efi_simple_text_output_protocol *this,
+ unsigned long attribute)
+{
+ unsigned int bold = EFI_ATTR_BOLD(attribute);
+ unsigned int fg = EFI_ATTR_FG(attribute);
+ unsigned int bg = EFI_ATTR_BG(attribute);
+
+ EFI_ENTRY("%p, %lx", this, attribute);
+
+ efi_con_mode.attribute = attribute;
+ if (attribute)
+ printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
+ else
+ printf(ESC"[0;37;40m");
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_clear_screen(
+ struct efi_simple_text_output_protocol *this)
+{
+ EFI_ENTRY("%p", this);
+
+ printf(ESC"[2J");
+ efi_con_mode.cursor_column = 0;
+ efi_con_mode.cursor_row = 0;
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_set_mode(
+ struct efi_simple_text_output_protocol *this,
+ unsigned long mode_number)
+{
+ EFI_ENTRY("%p, %ld", this, mode_number);
+
+ if (mode_number >= efi_con_mode.max_mode)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+
+ if (!efi_cout_modes[mode_number].present)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+
+ efi_con_mode.mode = mode_number;
+ EFI_CALL(efi_cout_clear_screen(this));
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_reset(
+ struct efi_simple_text_output_protocol *this,
+ char extended_verification)
+{
+ EFI_ENTRY("%p, %d", this, extended_verification);
+
+ /* Clear screen */
+ EFI_CALL(efi_cout_clear_screen(this));
+ /* Set default colors */
+ efi_con_mode.attribute = 0x07;
+ printf(ESC "[0;37;40m");
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_cout_set_cursor_position(
+ struct efi_simple_text_output_protocol *this,
+ unsigned long column, unsigned long row)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct simple_text_output_mode *con = &efi_con_mode;
+ struct cout_mode *mode = &efi_cout_modes[con->mode];
+
+ EFI_ENTRY("%p, %ld, %ld", this, column, row);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (row >= mode->rows || column >= mode->columns) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ /*
+ * Set cursor position by sending CSI H.
+ * EFI origin is [0, 0], terminal origin is [1, 1].
+ */
+ printf(ESC "[%d;%dH", (int)row + 1, (int)column + 1);
+ efi_con_mode.cursor_column = column;
+ efi_con_mode.cursor_row = row;
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_cout_enable_cursor(
+ struct efi_simple_text_output_protocol *this,
+ bool enable)
+{
+ EFI_ENTRY("%p, %d", this, enable);
+
+ printf(ESC"[?25%c", enable ? 'h' : 'l');
+ efi_con_mode.cursor_visible = !!enable;
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+struct efi_simple_text_output_protocol efi_con_out = {
+ .reset = efi_cout_reset,
+ .output_string = efi_cout_output_string,
+ .test_string = efi_cout_test_string,
+ .query_mode = efi_cout_query_mode,
+ .set_mode = efi_cout_set_mode,
+ .set_attribute = efi_cout_set_attribute,
+ .clear_screen = efi_cout_clear_screen,
+ .set_cursor_position = efi_cout_set_cursor_position,
+ .enable_cursor = efi_cout_enable_cursor,
+ .mode = (void*)&efi_con_mode,
+};
+
+/**
+ * struct efi_cin_notify_function - registered console input notify function
+ *
+ * @link: link to list
+ * @key: key to notify
+ * @function: function to call
+ */
+struct efi_cin_notify_function {
+ struct list_head link;
+ struct efi_key_data key;
+ efi_status_t (EFIAPI *function)
+ (struct efi_key_data *key_data);
+};
+
+static bool key_available;
+static struct efi_key_data next_key;
+static LIST_HEAD(cin_notify_functions);
+
+/**
+ * set_shift_mask() - set shift mask
+ *
+ * @mod: Xterm shift mask
+ * @key_state: receives the state of the shift, alt, control, and logo keys
+ */
+void set_shift_mask(int mod, struct efi_key_state *key_state)
+{
+ key_state->key_shift_state = EFI_SHIFT_STATE_VALID;
+ if (mod) {
+ --mod;
+ if (mod & 1)
+ key_state->key_shift_state |= EFI_LEFT_SHIFT_PRESSED;
+ if (mod & 2)
+ key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
+ if (mod & 4)
+ key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
+ if (!mod || (mod & 8))
+ key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
+ }
+}
+
+/**
+ * analyze_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
+ *
+ * This gets called when we have already parsed CSI.
+ *
+ * @key_state: receives the state of the shift, alt, control, and logo keys
+ * @return: the unmodified code
+ */
+static int analyze_modifiers(struct efi_key_state *key_state)
+{
+ int c, mod = 0, ret = 0;
+
+ c = getc();
+
+ if (c != ';') {
+ ret = c;
+ if (c == '~')
+ goto out;
+ c = getc();
+ }
+ for (;;) {
+ switch (c) {
+ case '0'...'9':
+ mod *= 10;
+ mod += c - '0';
+ /* fall through */
+ case ';':
+ c = getc();
+ break;
+ default:
+ goto out;
+ }
+ }
+out:
+ set_shift_mask(mod, key_state);
+ if (!ret)
+ ret = c;
+ return ret;
+}
+
+/**
+ * efi_cin_read_key() - read a key from the console input
+ *
+ * @key: - key received
+ * Return: - status code
+ */
+static efi_status_t efi_cin_read_key(struct efi_key_data *key)
+{
+ struct efi_input_key pressed_key = {
+ .scan_code = 0,
+ .unicode_char = 0,
+ };
+ s32 ch;
+
+ if (console_read_unicode(&ch))
+ return EFI_NOT_READY;
+
+ key->key_state.key_shift_state = EFI_SHIFT_STATE_INVALID;
+ key->key_state.key_toggle_state = EFI_TOGGLE_STATE_INVALID;
+
+ /* We do not support multi-word codes */
+ if (ch >= 0x10000)
+ ch = '?';
+
+ switch (ch) {
+ case 0x1b:
+ /*
+ * Xterm Control Sequences
+ * https://www.xfree86.org/4.8.0/ctlseqs.html
+ */
+ ch = getc();
+ switch (ch) {
+ case cESC: /* ESC */
+ pressed_key.scan_code = 23;
+ break;
+ case 'O': /* F1 - F4, End */
+ ch = getc();
+ /* consider modifiers */
+ if (ch == 'F') { /* End */
+ pressed_key.scan_code = 6;
+ break;
+ } else if (ch < 'P') {
+ set_shift_mask(ch - '0', &key->key_state);
+ ch = getc();
+ }
+ pressed_key.scan_code = ch - 'P' + 11;
+ break;
+ case '[':
+ ch = getc();
+ switch (ch) {
+ case 'A'...'D': /* up, down right, left */
+ pressed_key.scan_code = ch - 'A' + 1;
+ break;
+ case 'F': /* End */
+ pressed_key.scan_code = 6;
+ break;
+ case 'H': /* Home */
+ pressed_key.scan_code = 5;
+ break;
+ case '1':
+ ch = analyze_modifiers(&key->key_state);
+ switch (ch) {
+ case '1'...'5': /* F1 - F5 */
+ pressed_key.scan_code = ch - '1' + 11;
+ break;
+ case '6'...'9': /* F5 - F8 */
+ pressed_key.scan_code = ch - '6' + 15;
+ break;
+ case 'A'...'D': /* up, down right, left */
+ pressed_key.scan_code = ch - 'A' + 1;
+ break;
+ case 'F': /* End */
+ pressed_key.scan_code = 6;
+ break;
+ case 'H': /* Home */
+ pressed_key.scan_code = 5;
+ break;
+ case '~': /* Home */
+ pressed_key.scan_code = 5;
+ break;
+ }
+ break;
+ case '2':
+ ch = analyze_modifiers(&key->key_state);
+ switch (ch) {
+ case '0'...'1': /* F9 - F10 */
+ pressed_key.scan_code = ch - '0' + 19;
+ break;
+ case '3'...'4': /* F11 - F12 */
+ pressed_key.scan_code = ch - '3' + 21;
+ break;
+ case '~': /* INS */
+ pressed_key.scan_code = 7;
+ break;
+ }
+ break;
+ case '3': /* DEL */
+ pressed_key.scan_code = 8;
+ analyze_modifiers(&key->key_state);
+ break;
+ case '5': /* PG UP */
+ pressed_key.scan_code = 9;
+ analyze_modifiers(&key->key_state);
+ break;
+ case '6': /* PG DOWN */
+ pressed_key.scan_code = 10;
+ analyze_modifiers(&key->key_state);
+ break;
+ } /* [ */
+ break;
+ default:
+ /* ALT key */
+ set_shift_mask(3, &key->key_state);
+ }
+ break;
+ case 0x7f:
+ /* Backspace */
+ ch = 0x08;
+ }
+ if (pressed_key.scan_code) {
+ key->key_state.key_shift_state |= EFI_SHIFT_STATE_VALID;
+ } else {
+ pressed_key.unicode_char = ch;
+
+ /*
+ * Assume left control key for control characters typically
+ * entered using the control key.
+ */
+ if (ch >= 0x01 && ch <= 0x1f) {
+ key->key_state.key_shift_state |=
+ EFI_SHIFT_STATE_VALID;
+ switch (ch) {
+ case 0x01 ... 0x07:
+ case 0x0b ... 0x0c:
+ case 0x0e ... 0x1f:
+ key->key_state.key_shift_state |=
+ EFI_LEFT_CONTROL_PRESSED;
+ }
+ }
+ }
+ key->key = pressed_key;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_cin_notify() - notify registered functions
+ */
+static void efi_cin_notify(void)
+{
+ struct efi_cin_notify_function *item;
+
+ list_for_each_entry(item, &cin_notify_functions, link) {
+ bool match = true;
+
+ /* We do not support toggle states */
+ if (item->key.key.unicode_char || item->key.key.scan_code) {
+ if (item->key.key.unicode_char !=
+ next_key.key.unicode_char ||
+ item->key.key.scan_code != next_key.key.scan_code)
+ match = false;
+ }
+ if (item->key.key_state.key_shift_state &&
+ item->key.key_state.key_shift_state !=
+ next_key.key_state.key_shift_state)
+ match = false;
+
+ if (match)
+ /* We don't bother about the return code */
+ EFI_CALL(item->function(&next_key));
+ }
+}
+
+/**
+ * efi_cin_check() - check if keyboard input is available
+ */
+static void efi_cin_check(void)
+{
+ efi_status_t ret;
+
+ if (key_available) {
+ efi_signal_event(efi_con_in.wait_for_key);
+ return;
+ }
+
+ if (tstc()) {
+ ret = efi_cin_read_key(&next_key);
+ if (ret == EFI_SUCCESS) {
+ key_available = true;
+
+ /* Notify registered functions */
+ efi_cin_notify();
+
+ /* Queue the wait for key event */
+ if (key_available)
+ efi_signal_event(efi_con_in.wait_for_key);
+ }
+ }
+}
+
+/**
+ * efi_cin_empty_buffer() - empty input buffer
+ */
+static void efi_cin_empty_buffer(void)
+{
+ while (tstc())
+ getc();
+ key_available = false;
+}
+
+/**
+ * efi_cin_reset_ex() - reset console input
+ *
+ * @this: - the extended simple text input protocol
+ * @extended_verification: - extended verification
+ *
+ * This function implements the reset service of the
+ * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: old value of the task priority level
+ */
+static efi_status_t EFIAPI efi_cin_reset_ex(
+ struct efi_simple_text_input_ex_protocol *this,
+ bool extended_verification)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %d", this, extended_verification);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ efi_cin_empty_buffer();
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_cin_read_key_stroke_ex() - read key stroke
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @key_data: key read from console
+ * Return: status code
+ *
+ * This function implements the ReadKeyStrokeEx service of the
+ * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_read_key_stroke_ex(
+ struct efi_simple_text_input_ex_protocol *this,
+ struct efi_key_data *key_data)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p", this, key_data);
+
+ /* Check parameters */
+ if (!this || !key_data) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* We don't do interrupts, so check for timers cooperatively */
+ efi_timer_check();
+
+ /* Enable console input after ExitBootServices */
+ efi_cin_check();
+
+ if (!key_available) {
+ ret = EFI_NOT_READY;
+ goto out;
+ }
+ /*
+ * CTRL+A - CTRL+Z have to be signaled as a - z.
+ * SHIFT+CTRL+A - SHIFT+CTRL+Z have to be signaled as A - Z.
+ */
+ switch (next_key.key.unicode_char) {
+ case 0x01 ... 0x07:
+ case 0x0b ... 0x0c:
+ case 0x0e ... 0x1a:
+ if (!(next_key.key_state.key_toggle_state &
+ EFI_CAPS_LOCK_ACTIVE) ^
+ !(next_key.key_state.key_shift_state &
+ (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)))
+ next_key.key.unicode_char += 0x40;
+ else
+ next_key.key.unicode_char += 0x60;
+ }
+ *key_data = next_key;
+ key_available = false;
+ efi_con_in.wait_for_key->is_signaled = false;
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_cin_set_state() - set toggle key state
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @key_toggle_state: pointer to key toggle state
+ * Return: status code
+ *
+ * This function implements the SetState service of the
+ * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_set_state(
+ struct efi_simple_text_input_ex_protocol *this,
+ u8 *key_toggle_state)
+{
+ EFI_ENTRY("%p, %p", this, key_toggle_state);
+ /*
+ * U-Boot supports multiple console input sources like serial and
+ * net console for which a key toggle state cannot be set at all.
+ *
+ * According to the UEFI specification it is allowable to not implement
+ * this service.
+ */
+ return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/**
+ * efi_cin_register_key_notify() - register key notification function
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @key_data: key to be notified
+ * @key_notify_function: function to be called if the key is pressed
+ * @notify_handle: handle for unregistering the notification
+ * Return: status code
+ *
+ * This function implements the SetState service of the
+ * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_register_key_notify(
+ struct efi_simple_text_input_ex_protocol *this,
+ struct efi_key_data *key_data,
+ efi_status_t (EFIAPI *key_notify_function)(
+ struct efi_key_data *key_data),
+ void **notify_handle)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct efi_cin_notify_function *notify_function;
+
+ EFI_ENTRY("%p, %p, %p, %p",
+ this, key_data, key_notify_function, notify_handle);
+
+ /* Check parameters */
+ if (!this || !key_data || !key_notify_function || !notify_handle) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
+ key_data->key.unicode_char,
+ key_data->key.scan_code,
+ key_data->key_state.key_shift_state,
+ key_data->key_state.key_toggle_state);
+
+ notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
+ if (!notify_function) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ notify_function->key = *key_data;
+ notify_function->function = key_notify_function;
+ list_add_tail(&notify_function->link, &cin_notify_functions);
+ *notify_handle = notify_function;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_cin_unregister_key_notify() - unregister key notification function
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @notification_handle: handle received when registering
+ * Return: status code
+ *
+ * This function implements the SetState service of the
+ * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_unregister_key_notify(
+ struct efi_simple_text_input_ex_protocol *this,
+ void *notification_handle)
+{
+ efi_status_t ret = EFI_INVALID_PARAMETER;
+ struct efi_cin_notify_function *item, *notify_function =
+ notification_handle;
+
+ EFI_ENTRY("%p, %p", this, notification_handle);
+
+ /* Check parameters */
+ if (!this || !notification_handle)
+ goto out;
+
+ list_for_each_entry(item, &cin_notify_functions, link) {
+ if (item == notify_function) {
+ ret = EFI_SUCCESS;
+ break;
+ }
+ }
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Remove the notify function */
+ list_del(&notify_function->link);
+ free(notify_function);
+out:
+ return EFI_EXIT(ret);
+}
+
+
+/**
+ * efi_cin_reset() - drain the input buffer
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @extended_verification: allow for exhaustive verification
+ * Return: status code
+ *
+ * This function implements the Reset service of the
+ * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_reset
+ (struct efi_simple_text_input_protocol *this,
+ bool extended_verification)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %d", this, extended_verification);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ efi_cin_empty_buffer();
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_cin_read_key_stroke() - read key stroke
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @key: key read from console
+ * Return: status code
+ *
+ * This function implements the ReadKeyStroke service of the
+ * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_read_key_stroke
+ (struct efi_simple_text_input_protocol *this,
+ struct efi_input_key *key)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p", this, key);
+
+ /* Check parameters */
+ if (!this || !key) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* We don't do interrupts, so check for timers cooperatively */
+ efi_timer_check();
+
+ /* Enable console input after ExitBootServices */
+ efi_cin_check();
+
+ if (!key_available) {
+ ret = EFI_NOT_READY;
+ goto out;
+ }
+ *key = next_key.key;
+ key_available = false;
+ efi_con_in.wait_for_key->is_signaled = false;
+out:
+ return EFI_EXIT(ret);
+}
+
+static struct efi_simple_text_input_ex_protocol efi_con_in_ex = {
+ .reset = efi_cin_reset_ex,
+ .read_key_stroke_ex = efi_cin_read_key_stroke_ex,
+ .wait_for_key_ex = NULL,
+ .set_state = efi_cin_set_state,
+ .register_key_notify = efi_cin_register_key_notify,
+ .unregister_key_notify = efi_cin_unregister_key_notify,
+};
+
+struct efi_simple_text_input_protocol efi_con_in = {
+ .reset = efi_cin_reset,
+ .read_key_stroke = efi_cin_read_key_stroke,
+ .wait_for_key = NULL,
+};
+
+static struct efi_event *console_timer_event;
+
+/*
+ * efi_console_timer_notify() - notify the console timer event
+ *
+ * @event: console timer event
+ * @context: not used
+ */
+static void EFIAPI efi_console_timer_notify(struct efi_event *event,
+ void *context)
+{
+ EFI_ENTRY("%p, %p", event, context);
+ efi_cin_check();
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_key_notify() - notify the wait for key event
+ *
+ * @event: wait for key event
+ * @context: not used
+ */
+static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
+{
+ EFI_ENTRY("%p, %p", event, context);
+ efi_cin_check();
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_console_register() - install the console protocols
+ *
+ * This function is called from do_bootefi_exec().
+ *
+ * Return: status code
+ */
+efi_status_t efi_console_register(void)
+{
+ efi_status_t r;
+ efi_handle_t console_output_handle;
+ efi_handle_t console_input_handle;
+
+ /* Set up mode information */
+ query_console_size();
+
+ /* Create handles */
+ r = efi_create_handle(&console_output_handle);
+ if (r != EFI_SUCCESS)
+ goto out_of_memory;
+
+ r = efi_add_protocol(console_output_handle,
+ &efi_guid_text_output_protocol, &efi_con_out);
+ if (r != EFI_SUCCESS)
+ goto out_of_memory;
+ systab.con_out_handle = console_output_handle;
+ systab.stderr_handle = console_output_handle;
+
+ r = efi_create_handle(&console_input_handle);
+ if (r != EFI_SUCCESS)
+ goto out_of_memory;
+
+ r = efi_add_protocol(console_input_handle,
+ &efi_guid_text_input_protocol, &efi_con_in);
+ if (r != EFI_SUCCESS)
+ goto out_of_memory;
+ systab.con_in_handle = console_input_handle;
+ r = efi_add_protocol(console_input_handle,
+ &efi_guid_text_input_ex_protocol, &efi_con_in_ex);
+ if (r != EFI_SUCCESS)
+ goto out_of_memory;
+
+ /* Create console events */
+ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
+ NULL, NULL, &efi_con_in.wait_for_key);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to register WaitForKey event\n");
+ return r;
+ }
+ efi_con_in_ex.wait_for_key_ex = efi_con_in.wait_for_key;
+ r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ efi_console_timer_notify, NULL, NULL,
+ &console_timer_event);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to register console event\n");
+ return r;
+ }
+ /* 5000 ns cycle is sufficient for 2 MBaud */
+ r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50);
+ if (r != EFI_SUCCESS)
+ printf("ERROR: Failed to set console timer\n");
+ return r;
+out_of_memory:
+ printf("ERROR: Out of memory\n");
+ return r;
+}
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
new file mode 100644
index 00000000..73f1fe75
--- /dev/null
+++ b/lib/efi_loader/efi_device_path.c
@@ -0,0 +1,1076 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI device path from u-boot device-model mapping
+ *
+ * (C) Copyright 2017 Rob Clark
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <usb.h>
+#include <mmc.h>
+#include <nvme.h>
+#include <efi_loader.h>
+#include <part.h>
+#include <sandboxblockdev.h>
+#include <asm-generic/unaligned.h>
+#include <linux/compat.h> /* U16_MAX */
+
+#ifdef CONFIG_SANDBOX
+const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
+#endif
+
+/* template END node: */
+static const struct efi_device_path END = {
+ .type = DEVICE_PATH_TYPE_END,
+ .sub_type = DEVICE_PATH_SUB_TYPE_END,
+ .length = sizeof(END),
+};
+
+/* template ROOT node: */
+static const struct efi_device_path_vendor ROOT = {
+ .dp = {
+ .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+ .length = sizeof(ROOT),
+ },
+ .guid = U_BOOT_GUID,
+};
+
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+/*
+ * Determine if an MMC device is an SD card.
+ *
+ * @desc block device descriptor
+ * @return true if the device is an SD card
+ */
+static bool is_sd(struct blk_desc *desc)
+{
+ struct mmc *mmc = find_mmc_device(desc->devnum);
+
+ if (!mmc)
+ return false;
+
+ return IS_SD(mmc) != 0U;
+}
+#endif
+
+static void *dp_alloc(size_t sz)
+{
+ void *buf;
+
+ if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
+ EFI_SUCCESS) {
+ debug("EFI: ERROR: out of memory in %s\n", __func__);
+ return NULL;
+ }
+
+ memset(buf, 0, sz);
+ return buf;
+}
+
+/*
+ * Iterate to next block in device-path, terminating (returning NULL)
+ * at /End* node.
+ */
+struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
+{
+ if (dp == NULL)
+ return NULL;
+ if (dp->type == DEVICE_PATH_TYPE_END)
+ return NULL;
+ dp = ((void *)dp) + dp->length;
+ if (dp->type == DEVICE_PATH_TYPE_END)
+ return NULL;
+ return (struct efi_device_path *)dp;
+}
+
+/*
+ * Compare two device-paths, stopping when the shorter of the two hits
+ * an End* node. This is useful to, for example, compare a device-path
+ * representing a device with one representing a file on the device, or
+ * a device with a parent device.
+ */
+int efi_dp_match(const struct efi_device_path *a,
+ const struct efi_device_path *b)
+{
+ while (1) {
+ int ret;
+
+ ret = memcmp(&a->length, &b->length, sizeof(a->length));
+ if (ret)
+ return ret;
+
+ ret = memcmp(a, b, a->length);
+ if (ret)
+ return ret;
+
+ a = efi_dp_next(a);
+ b = efi_dp_next(b);
+
+ if (!a || !b)
+ return 0;
+ }
+}
+
+/*
+ * We can have device paths that start with a USB WWID or a USB Class node,
+ * and a few other cases which don't encode the full device path with bus
+ * hierarchy:
+ *
+ * - MESSAGING:USB_WWID
+ * - MESSAGING:USB_CLASS
+ * - MEDIA:FILE_PATH
+ * - MEDIA:HARD_DRIVE
+ * - MESSAGING:URI
+ *
+ * See UEFI spec (section 3.1.2, about short-form device-paths)
+ */
+static struct efi_device_path *shorten_path(struct efi_device_path *dp)
+{
+ while (dp) {
+ /*
+ * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
+ * in practice fallback.efi just uses MEDIA:HARD_DRIVE
+ * so not sure when we would see these other cases.
+ */
+ if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
+ EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
+ EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
+ return dp;
+
+ dp = efi_dp_next(dp);
+ }
+
+ return dp;
+}
+
+static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
+ struct efi_device_path **rem)
+{
+ struct efi_object *efiobj;
+ efi_uintn_t dp_size = efi_dp_instance_size(dp);
+
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ struct efi_handler *handler;
+ struct efi_device_path *obj_dp;
+ efi_status_t ret;
+
+ ret = efi_search_protocol(efiobj,
+ &efi_guid_device_path, &handler);
+ if (ret != EFI_SUCCESS)
+ continue;
+ obj_dp = handler->protocol_interface;
+
+ do {
+ if (efi_dp_match(dp, obj_dp) == 0) {
+ if (rem) {
+ /*
+ * Allow partial matches, but inform
+ * the caller.
+ */
+ *rem = ((void *)dp) +
+ efi_dp_instance_size(obj_dp);
+ return efiobj;
+ } else {
+ /* Only return on exact matches */
+ if (efi_dp_instance_size(obj_dp) ==
+ dp_size)
+ return efiobj;
+ }
+ }
+
+ obj_dp = shorten_path(efi_dp_next(obj_dp));
+ } while (short_path && obj_dp);
+ }
+
+ return NULL;
+}
+
+/*
+ * Find an efiobj from device-path, if 'rem' is not NULL, returns the
+ * remaining part of the device path after the matched object.
+ */
+struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
+ struct efi_device_path **rem)
+{
+ struct efi_object *efiobj;
+
+ /* Search for an exact match first */
+ efiobj = find_obj(dp, false, NULL);
+
+ /* Then for a fuzzy match */
+ if (!efiobj)
+ efiobj = find_obj(dp, false, rem);
+
+ /* And now for a fuzzy short match */
+ if (!efiobj)
+ efiobj = find_obj(dp, true, rem);
+
+ return efiobj;
+}
+
+/*
+ * Determine the last device path node that is not the end node.
+ *
+ * @dp device path
+ * @return last node before the end node if it exists
+ * otherwise NULL
+ */
+const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
+{
+ struct efi_device_path *ret;
+
+ if (!dp || dp->type == DEVICE_PATH_TYPE_END)
+ return NULL;
+ while (dp) {
+ ret = (struct efi_device_path *)dp;
+ dp = efi_dp_next(dp);
+ }
+ return ret;
+}
+
+/* get size of the first device path instance excluding end node */
+efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
+{
+ efi_uintn_t sz = 0;
+
+ if (!dp || dp->type == DEVICE_PATH_TYPE_END)
+ return 0;
+ while (dp) {
+ sz += dp->length;
+ dp = efi_dp_next(dp);
+ }
+
+ return sz;
+}
+
+/* get size of multi-instance device path excluding end node */
+efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
+{
+ const struct efi_device_path *p = dp;
+
+ if (!p)
+ return 0;
+ while (p->type != DEVICE_PATH_TYPE_END ||
+ p->sub_type != DEVICE_PATH_SUB_TYPE_END)
+ p = (void *)p + p->length;
+
+ return (void *)p - (void *)dp;
+}
+
+/* copy multi-instance device path */
+struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
+{
+ struct efi_device_path *ndp;
+ size_t sz = efi_dp_size(dp) + sizeof(END);
+
+ if (!dp)
+ return NULL;
+
+ ndp = dp_alloc(sz);
+ if (!ndp)
+ return NULL;
+ memcpy(ndp, dp, sz);
+
+ return ndp;
+}
+
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+ const struct efi_device_path *dp2)
+{
+ struct efi_device_path *ret;
+
+ if (!dp1 && !dp2) {
+ /* return an end node */
+ ret = efi_dp_dup(&END);
+ } else if (!dp1) {
+ ret = efi_dp_dup(dp2);
+ } else if (!dp2) {
+ ret = efi_dp_dup(dp1);
+ } else {
+ /* both dp1 and dp2 are non-null */
+ unsigned sz1 = efi_dp_size(dp1);
+ unsigned sz2 = efi_dp_size(dp2);
+ void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+ if (!p)
+ return NULL;
+ memcpy(p, dp1, sz1);
+ /* the end node of the second device path has to be retained */
+ memcpy(p + sz1, dp2, sz2 + sizeof(END));
+ ret = p;
+ }
+
+ return ret;
+}
+
+struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
+ const struct efi_device_path *node)
+{
+ struct efi_device_path *ret;
+
+ if (!node && !dp) {
+ ret = efi_dp_dup(&END);
+ } else if (!node) {
+ ret = efi_dp_dup(dp);
+ } else if (!dp) {
+ size_t sz = node->length;
+ void *p = dp_alloc(sz + sizeof(END));
+ if (!p)
+ return NULL;
+ memcpy(p, node, sz);
+ memcpy(p + sz, &END, sizeof(END));
+ ret = p;
+ } else {
+ /* both dp and node are non-null */
+ size_t sz = efi_dp_size(dp);
+ void *p = dp_alloc(sz + node->length + sizeof(END));
+ if (!p)
+ return NULL;
+ memcpy(p, dp, sz);
+ memcpy(p + sz, node, node->length);
+ memcpy(p + sz + node->length, &END, sizeof(END));
+ ret = p;
+ }
+
+ return ret;
+}
+
+struct efi_device_path *efi_dp_create_device_node(const u8 type,
+ const u8 sub_type,
+ const u16 length)
+{
+ struct efi_device_path *ret;
+
+ if (length < sizeof(struct efi_device_path))
+ return NULL;
+
+ ret = dp_alloc(length);
+ if (!ret)
+ return ret;
+ ret->type = type;
+ ret->sub_type = sub_type;
+ ret->length = length;
+ return ret;
+}
+
+struct efi_device_path *efi_dp_append_instance(
+ const struct efi_device_path *dp,
+ const struct efi_device_path *dpi)
+{
+ size_t sz, szi;
+ struct efi_device_path *p, *ret;
+
+ if (!dpi)
+ return NULL;
+ if (!dp)
+ return efi_dp_dup(dpi);
+ sz = efi_dp_size(dp);
+ szi = efi_dp_instance_size(dpi);
+ p = dp_alloc(sz + szi + 2 * sizeof(END));
+ if (!p)
+ return NULL;
+ ret = p;
+ memcpy(p, dp, sz + sizeof(END));
+ p = (void *)p + sz;
+ p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
+ p = (void *)p + sizeof(END);
+ memcpy(p, dpi, szi);
+ p = (void *)p + szi;
+ memcpy(p, &END, sizeof(END));
+ return ret;
+}
+
+struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
+ efi_uintn_t *size)
+{
+ size_t sz;
+ struct efi_device_path *p;
+
+ if (size)
+ *size = 0;
+ if (!dp || !*dp)
+ return NULL;
+ sz = efi_dp_instance_size(*dp);
+ p = dp_alloc(sz + sizeof(END));
+ if (!p)
+ return NULL;
+ memcpy(p, *dp, sz + sizeof(END));
+ *dp = (void *)*dp + sz;
+ if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
+ *dp = (void *)*dp + sizeof(END);
+ else
+ *dp = NULL;
+ if (size)
+ *size = sz + sizeof(END);
+ return p;
+}
+
+bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
+{
+ const struct efi_device_path *p = dp;
+
+ if (!p)
+ return false;
+ while (p->type != DEVICE_PATH_TYPE_END)
+ p = (void *)p + p->length;
+ return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
+}
+
+#ifdef CONFIG_DM
+/* size of device-path not including END node for device and all parents
+ * up to the root device.
+ */
+__maybe_unused static unsigned int dp_size(struct udevice *dev)
+{
+ if (!dev || !dev->driver)
+ return sizeof(ROOT);
+
+ switch (dev->driver->id) {
+ case UCLASS_ROOT:
+ case UCLASS_SIMPLE_BUS:
+ /* stop traversing parents at this point: */
+ return sizeof(ROOT);
+ case UCLASS_ETH:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_mac_addr);
+#ifdef CONFIG_BLK
+ case UCLASS_BLK:
+ switch (dev->parent->uclass->uc_drv->id) {
+#ifdef CONFIG_IDE
+ case UCLASS_IDE:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_atapi);
+#endif
+#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
+ case UCLASS_SCSI:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_scsi);
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+ case UCLASS_MMC:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_sd_mmc_path);
+#endif
+#if defined(CONFIG_NVME)
+ case UCLASS_NVME:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_nvme);
+#endif
+#ifdef CONFIG_SANDBOX
+ case UCLASS_ROOT:
+ /*
+ * Sandbox's host device will be represented
+ * as vendor device with extra one byte for
+ * device number
+ */
+ return dp_size(dev->parent)
+ + sizeof(struct efi_device_path_vendor) + 1;
+#endif
+ default:
+ return dp_size(dev->parent);
+ }
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+ case UCLASS_MMC:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_sd_mmc_path);
+#endif
+ case UCLASS_MASS_STORAGE:
+ case UCLASS_USB_HUB:
+ return dp_size(dev->parent) +
+ sizeof(struct efi_device_path_usb_class);
+ default:
+ /* just skip over unknown classes: */
+ return dp_size(dev->parent);
+ }
+}
+
+/*
+ * Recursively build a device path.
+ *
+ * @buf pointer to the end of the device path
+ * @dev device
+ * @return pointer to the end of the device path
+ */
+__maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
+{
+ if (!dev || !dev->driver)
+ return buf;
+
+ switch (dev->driver->id) {
+ case UCLASS_ROOT:
+ case UCLASS_SIMPLE_BUS: {
+ /* stop traversing parents at this point: */
+ struct efi_device_path_vendor *vdp = buf;
+ *vdp = ROOT;
+ return &vdp[1];
+ }
+#ifdef CONFIG_DM_ETH
+ case UCLASS_ETH: {
+ struct efi_device_path_mac_addr *dp =
+ dp_fill(buf, dev->parent);
+ struct eth_pdata *pdata = dev->platdata;
+
+ dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
+ dp->dp.length = sizeof(*dp);
+ memset(&dp->mac, 0, sizeof(dp->mac));
+ /* We only support IPv4 */
+ memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
+ /* Ethernet */
+ dp->if_type = 1;
+ return &dp[1];
+ }
+#endif
+#ifdef CONFIG_BLK
+ case UCLASS_BLK:
+ switch (dev->parent->uclass->uc_drv->id) {
+#ifdef CONFIG_SANDBOX
+ case UCLASS_ROOT: {
+ /* stop traversing parents at this point: */
+ struct efi_device_path_vendor *dp = buf;
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ dp_fill(buf, dev->parent);
+ dp = buf;
+ ++dp;
+ dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+ dp->dp.length = sizeof(*dp) + 1;
+ memcpy(&dp->guid, &efi_guid_host_dev,
+ sizeof(efi_guid_t));
+ dp->vendor_data[0] = desc->devnum;
+ return &dp->vendor_data[1];
+ }
+#endif
+#ifdef CONFIG_IDE
+ case UCLASS_IDE: {
+ struct efi_device_path_atapi *dp =
+ dp_fill(buf, dev->parent);
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
+ dp->dp.length = sizeof(*dp);
+ dp->logical_unit_number = desc->devnum;
+ dp->primary_secondary = IDE_BUS(desc->devnum);
+ dp->slave_master = desc->devnum %
+ (CONFIG_SYS_IDE_MAXDEVICE /
+ CONFIG_SYS_IDE_MAXBUS);
+ return &dp[1];
+ }
+#endif
+#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
+ case UCLASS_SCSI: {
+ struct efi_device_path_scsi *dp =
+ dp_fill(buf, dev->parent);
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
+ dp->dp.length = sizeof(*dp);
+ dp->logical_unit_number = desc->lun;
+ dp->target_id = desc->target;
+ return &dp[1];
+ }
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+ case UCLASS_MMC: {
+ struct efi_device_path_sd_mmc_path *sddp =
+ dp_fill(buf, dev->parent);
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+ sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ sddp->dp.sub_type = is_sd(desc) ?
+ DEVICE_PATH_SUB_TYPE_MSG_SD :
+ DEVICE_PATH_SUB_TYPE_MSG_MMC;
+ sddp->dp.length = sizeof(*sddp);
+ sddp->slot_number = dev->seq;
+ return &sddp[1];
+ }
+#endif
+#if defined(CONFIG_NVME)
+ case UCLASS_NVME: {
+ struct efi_device_path_nvme *dp =
+ dp_fill(buf, dev->parent);
+ u32 ns_id;
+
+ dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_NVME;
+ dp->dp.length = sizeof(*dp);
+ nvme_get_namespace_id(dev, &ns_id, dp->eui64);
+ memcpy(&dp->ns_id, &ns_id, sizeof(ns_id));
+ return &dp[1];
+ }
+#endif
+ default:
+ debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
+ __FILE__, __LINE__, __func__,
+ dev->name, dev->parent->uclass->uc_drv->id);
+ return dp_fill(buf, dev->parent);
+ }
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+ case UCLASS_MMC: {
+ struct efi_device_path_sd_mmc_path *sddp =
+ dp_fill(buf, dev->parent);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct blk_desc *desc = mmc_get_blk_desc(mmc);
+
+ sddp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ sddp->dp.sub_type = is_sd(desc) ?
+ DEVICE_PATH_SUB_TYPE_MSG_SD :
+ DEVICE_PATH_SUB_TYPE_MSG_MMC;
+ sddp->dp.length = sizeof(*sddp);
+ sddp->slot_number = dev->seq;
+
+ return &sddp[1];
+ }
+#endif
+ case UCLASS_MASS_STORAGE:
+ case UCLASS_USB_HUB: {
+ struct efi_device_path_usb_class *udp =
+ dp_fill(buf, dev->parent);
+ struct usb_device *udev = dev_get_parent_priv(dev);
+ struct usb_device_descriptor *desc = &udev->descriptor;
+
+ udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
+ udp->dp.length = sizeof(*udp);
+ udp->vendor_id = desc->idVendor;
+ udp->product_id = desc->idProduct;
+ udp->device_class = desc->bDeviceClass;
+ udp->device_subclass = desc->bDeviceSubClass;
+ udp->device_protocol = desc->bDeviceProtocol;
+
+ return &udp[1];
+ }
+ default:
+ debug("%s(%u) %s: unhandled device class: %s (%u)\n",
+ __FILE__, __LINE__, __func__,
+ dev->name, dev->driver->id);
+ return dp_fill(buf, dev->parent);
+ }
+}
+#endif
+
+static unsigned dp_part_size(struct blk_desc *desc, int part)
+{
+ unsigned dpsize;
+
+#ifdef CONFIG_BLK
+ {
+ struct udevice *dev;
+ int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
+
+ if (ret)
+ dev = desc->bdev->parent;
+ dpsize = dp_size(dev);
+ }
+#else
+ dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
+#endif
+
+ if (part == 0) /* the actual disk, not a partition */
+ return dpsize;
+
+ if (desc->part_type == PART_TYPE_ISO)
+ dpsize += sizeof(struct efi_device_path_cdrom_path);
+ else
+ dpsize += sizeof(struct efi_device_path_hard_drive_path);
+
+ return dpsize;
+}
+
+/*
+ * Create a device node for a block device partition.
+ *
+ * @buf buffer to which the device path is written
+ * @desc block device descriptor
+ * @part partition number, 0 identifies a block device
+ */
+static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
+{
+ disk_partition_t info;
+
+ part_get_info(desc, part, &info);
+
+ if (desc->part_type == PART_TYPE_ISO) {
+ struct efi_device_path_cdrom_path *cddp = buf;
+
+ cddp->boot_entry = part;
+ cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+ cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
+ cddp->dp.length = sizeof(*cddp);
+ cddp->partition_start = info.start;
+ cddp->partition_size = info.size;
+
+ buf = &cddp[1];
+ } else {
+ struct efi_device_path_hard_drive_path *hddp = buf;
+
+ hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+ hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
+ hddp->dp.length = sizeof(*hddp);
+ hddp->partition_number = part;
+ hddp->partition_start = info.start;
+ hddp->partition_end = info.size;
+ if (desc->part_type == PART_TYPE_EFI)
+ hddp->partmap_type = 2;
+ else
+ hddp->partmap_type = 1;
+
+ switch (desc->sig_type) {
+ case SIG_TYPE_NONE:
+ default:
+ hddp->signature_type = 0;
+ memset(hddp->partition_signature, 0,
+ sizeof(hddp->partition_signature));
+ break;
+ case SIG_TYPE_MBR:
+ hddp->signature_type = 1;
+ memset(hddp->partition_signature, 0,
+ sizeof(hddp->partition_signature));
+ memcpy(hddp->partition_signature, &desc->mbr_sig,
+ sizeof(desc->mbr_sig));
+ break;
+ case SIG_TYPE_GUID:
+ hddp->signature_type = 2;
+ memcpy(hddp->partition_signature, &desc->guid_sig,
+ sizeof(hddp->partition_signature));
+ break;
+ }
+
+ buf = &hddp[1];
+ }
+
+ return buf;
+}
+
+/*
+ * Create a device path for a block device or one of its partitions.
+ *
+ * @buf buffer to which the device path is written
+ * @desc block device descriptor
+ * @part partition number, 0 identifies a block device
+ */
+static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
+{
+#ifdef CONFIG_BLK
+ {
+ struct udevice *dev;
+ int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
+
+ if (ret)
+ dev = desc->bdev->parent;
+ buf = dp_fill(buf, dev);
+ }
+#else
+ /*
+ * We *could* make a more accurate path, by looking at if_type
+ * and handling all the different cases like we do for non-
+ * legacy (i.e. CONFIG_BLK=y) case. But most important thing
+ * is just to have a unique device-path for if_type+devnum.
+ * So map things to a fictitious USB device.
+ */
+ struct efi_device_path_usb *udp;
+
+ memcpy(buf, &ROOT, sizeof(ROOT));
+ buf += sizeof(ROOT);
+
+ udp = buf;
+ udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
+ udp->dp.length = sizeof(*udp);
+ udp->parent_port_number = desc->if_type;
+ udp->usb_interface = desc->devnum;
+ buf = &udp[1];
+#endif
+
+ if (part == 0) /* the actual disk, not a partition */
+ return buf;
+
+ return dp_part_node(buf, desc, part);
+}
+
+/* Construct a device-path from a partition on a block device: */
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
+{
+ void *buf, *start;
+
+ start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
+ if (!buf)
+ return NULL;
+
+ buf = dp_part_fill(buf, desc, part);
+
+ *((struct efi_device_path *)buf) = END;
+
+ return start;
+}
+
+/*
+ * Create a device node for a block device partition.
+ *
+ * @buf buffer to which the device path is written
+ * @desc block device descriptor
+ * @part partition number, 0 identifies a block device
+ */
+struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
+{
+ efi_uintn_t dpsize;
+ void *buf;
+
+ if (desc->part_type == PART_TYPE_ISO)
+ dpsize = sizeof(struct efi_device_path_cdrom_path);
+ else
+ dpsize = sizeof(struct efi_device_path_hard_drive_path);
+ buf = dp_alloc(dpsize);
+
+ dp_part_node(buf, desc, part);
+
+ return buf;
+}
+
+/**
+ * path_to_uefi() - convert UTF-8 path to an UEFI style path
+ *
+ * Convert UTF-8 path to a UEFI style path (i.e. with backslashes as path
+ * separators and UTF-16).
+ *
+ * @src: source buffer
+ * @uefi: target buffer, possibly unaligned
+ */
+static void path_to_uefi(void *uefi, const char *src)
+{
+ u16 *pos = uefi;
+
+ /*
+ * efi_set_bootdev() calls this routine indirectly before the UEFI
+ * subsystem is initialized. So we cannot assume unaligned access to be
+ * enabled.
+ */
+ allow_unaligned();
+
+ while (*src) {
+ s32 code = utf8_get(&src);
+
+ if (code < 0)
+ code = '?';
+ else if (code == '/')
+ code = '\\';
+ utf16_put(code, &pos);
+ }
+ *pos = 0;
+}
+
+/*
+ * If desc is NULL, this creates a path with only the file component,
+ * otherwise it creates a full path with both device and file components
+ */
+struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+ const char *path)
+{
+ struct efi_device_path_file_path *fp;
+ void *buf, *start;
+ size_t dpsize = 0, fpsize;
+
+ if (desc)
+ dpsize = dp_part_size(desc, part);
+
+ fpsize = sizeof(struct efi_device_path) +
+ 2 * (utf8_utf16_strlen(path) + 1);
+ if (fpsize > U16_MAX)
+ return NULL;
+
+ dpsize += fpsize;
+
+ start = buf = dp_alloc(dpsize + sizeof(END));
+ if (!buf)
+ return NULL;
+
+ if (desc)
+ buf = dp_part_fill(buf, desc, part);
+
+ /* add file-path: */
+ fp = buf;
+ fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+ fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
+ fp->dp.length = (u16)fpsize;
+ path_to_uefi(fp->str, path);
+ buf += fpsize;
+
+ *((struct efi_device_path *)buf) = END;
+
+ return start;
+}
+
+#ifdef CONFIG_NET
+struct efi_device_path *efi_dp_from_eth(void)
+{
+#ifndef CONFIG_DM_ETH
+ struct efi_device_path_mac_addr *ndp;
+#endif
+ void *buf, *start;
+ unsigned dpsize = 0;
+
+ assert(eth_get_dev());
+
+#ifdef CONFIG_DM_ETH
+ dpsize += dp_size(eth_get_dev());
+#else
+ dpsize += sizeof(ROOT);
+ dpsize += sizeof(*ndp);
+#endif
+
+ start = buf = dp_alloc(dpsize + sizeof(END));
+ if (!buf)
+ return NULL;
+
+#ifdef CONFIG_DM_ETH
+ buf = dp_fill(buf, eth_get_dev());
+#else
+ memcpy(buf, &ROOT, sizeof(ROOT));
+ buf += sizeof(ROOT);
+
+ ndp = buf;
+ ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
+ ndp->dp.length = sizeof(*ndp);
+ ndp->if_type = 1; /* Ethernet */
+ memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
+ buf = &ndp[1];
+#endif
+
+ *((struct efi_device_path *)buf) = END;
+
+ return start;
+}
+#endif
+
+/* Construct a device-path for memory-mapped image */
+struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
+ uint64_t start_address,
+ uint64_t end_address)
+{
+ struct efi_device_path_memory *mdp;
+ void *buf, *start;
+
+ start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
+ if (!buf)
+ return NULL;
+
+ mdp = buf;
+ mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
+ mdp->dp.length = sizeof(*mdp);
+ mdp->memory_type = memory_type;
+ mdp->start_address = start_address;
+ mdp->end_address = end_address;
+ buf = &mdp[1];
+
+ *((struct efi_device_path *)buf) = END;
+
+ return start;
+}
+
+/**
+ * efi_dp_split_file_path() - split of relative file path from device path
+ *
+ * Given a device path indicating a file on a device, separate the device
+ * path in two: the device path of the actual device and the file path
+ * relative to this device.
+ *
+ * @full_path: device path including device and file path
+ * @device_path: path of the device
+ * @file_path: relative path of the file or NULL if there is none
+ * Return: status code
+ */
+efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
+ struct efi_device_path **device_path,
+ struct efi_device_path **file_path)
+{
+ struct efi_device_path *p, *dp, *fp = NULL;
+
+ *device_path = NULL;
+ *file_path = NULL;
+ dp = efi_dp_dup(full_path);
+ if (!dp)
+ return EFI_OUT_OF_RESOURCES;
+ p = dp;
+ while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
+ p = efi_dp_next(p);
+ if (!p)
+ goto out;
+ }
+ fp = efi_dp_dup(p);
+ if (!fp)
+ return EFI_OUT_OF_RESOURCES;
+ p->type = DEVICE_PATH_TYPE_END;
+ p->sub_type = DEVICE_PATH_SUB_TYPE_END;
+ p->length = sizeof(*p);
+
+out:
+ *device_path = dp;
+ *file_path = fp;
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_dp_from_name() - convert U-Boot device and file path to device path
+ *
+ * @dev: U-Boot device, e.g. 'mmc'
+ * @devnr: U-Boot device number, e.g. 1 for 'mmc:1'
+ * @path: file path relative to U-Boot device, may be NULL
+ * @device: pointer to receive device path of the device
+ * @file: pointer to receive device path for the file
+ * Return: status code
+ */
+efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
+ const char *path,
+ struct efi_device_path **device,
+ struct efi_device_path **file)
+{
+ int is_net;
+ struct blk_desc *desc = NULL;
+ disk_partition_t fs_partition;
+ int part = 0;
+ char filename[32] = { 0 }; /* dp->str is u16[32] long */
+ char *s;
+
+ if (path && !file)
+ return EFI_INVALID_PARAMETER;
+
+ is_net = !strcmp(dev, "Net");
+ if (!is_net) {
+ part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
+ 1);
+ if (part < 0 || !desc)
+ return EFI_INVALID_PARAMETER;
+
+ if (device)
+ *device = efi_dp_from_part(desc, part);
+ } else {
+#ifdef CONFIG_NET
+ if (device)
+ *device = efi_dp_from_eth();
+#endif
+ }
+
+ if (!path)
+ return EFI_SUCCESS;
+
+ snprintf(filename, sizeof(filename), "%s", path);
+ /* DOS style file path: */
+ s = filename;
+ while ((s = strchr(s, '/')))
+ *s++ = '\\';
+ *file = efi_dp_from_file(is_net ? NULL : desc, part, filename);
+
+ if (!*file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
new file mode 100644
index 00000000..af1adbb7
--- /dev/null
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI device path interface
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+
+#define MAC_OUTPUT_LEN 22
+#define UNKNOWN_OUTPUT_LEN 23
+
+#define MAX_NODE_LEN 512
+#define MAX_PATH_LEN 1024
+
+const efi_guid_t efi_guid_device_path_to_text_protocol =
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+
+/**
+ * efi_str_to_u16() - convert ASCII string to UTF-16
+ *
+ * A u16 buffer is allocated from pool. The ASCII string is copied to the u16
+ * buffer.
+ *
+ * @str: ASCII string
+ * Return: UTF-16 string. NULL if out of memory.
+ */
+static u16 *efi_str_to_u16(char *str)
+{
+ efi_uintn_t len;
+ u16 *out, *dst;
+ efi_status_t ret;
+
+ len = sizeof(u16) * (utf8_utf16_strlen(str) + 1);
+ ret = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, len, (void **)&out);
+ if (ret != EFI_SUCCESS)
+ return NULL;
+ dst = out;
+ utf8_utf16_strcpy(&dst, str);
+ return out;
+}
+
+static char *dp_unknown(char *s, struct efi_device_path *dp)
+{
+ s += sprintf(s, "UNKNOWN(%04x,%04x)", dp->type, dp->sub_type);
+ return s;
+}
+
+static char *dp_hardware(char *s, struct efi_device_path *dp)
+{
+ switch (dp->sub_type) {
+ case DEVICE_PATH_SUB_TYPE_MEMORY: {
+ struct efi_device_path_memory *mdp =
+ (struct efi_device_path_memory *)dp;
+ s += sprintf(s, "MemoryMapped(0x%x,0x%llx,0x%llx)",
+ mdp->memory_type,
+ mdp->start_address,
+ mdp->end_address);
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_VENDOR: {
+ int i, n;
+ struct efi_device_path_vendor *vdp =
+ (struct efi_device_path_vendor *)dp;
+
+ s += sprintf(s, "VenHw(%pUl", &vdp->guid);
+ n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor);
+ if (n > 0) {
+ s += sprintf(s, ",");
+ for (i = 0; i < n; ++i)
+ s += sprintf(s, "%02x", vdp->vendor_data[i]);
+ }
+ s += sprintf(s, ")");
+ break;
+ }
+ default:
+ s = dp_unknown(s, dp);
+ break;
+ }
+ return s;
+}
+
+static char *dp_acpi(char *s, struct efi_device_path *dp)
+{
+ switch (dp->sub_type) {
+ case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: {
+ struct efi_device_path_acpi_path *adp =
+ (struct efi_device_path_acpi_path *)dp;
+
+ s += sprintf(s, "Acpi(PNP%04X,%d)", EISA_PNP_NUM(adp->hid),
+ adp->uid);
+ break;
+ }
+ default:
+ s = dp_unknown(s, dp);
+ break;
+ }
+ return s;
+}
+
+static char *dp_msging(char *s, struct efi_device_path *dp)
+{
+ switch (dp->sub_type) {
+ case DEVICE_PATH_SUB_TYPE_MSG_ATAPI: {
+ struct efi_device_path_atapi *ide =
+ (struct efi_device_path_atapi *)dp;
+ s += sprintf(s, "Ata(%d,%d,%d)", ide->primary_secondary,
+ ide->slave_master, ide->logical_unit_number);
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_SCSI: {
+ struct efi_device_path_scsi *ide =
+ (struct efi_device_path_scsi *)dp;
+ s += sprintf(s, "Scsi(%u,%u)", ide->target_id,
+ ide->logical_unit_number);
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_USB: {
+ struct efi_device_path_usb *udp =
+ (struct efi_device_path_usb *)dp;
+ s += sprintf(s, "USB(0x%x,0x%x)", udp->parent_port_number,
+ udp->usb_interface);
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
+ int i, n = sizeof(struct efi_mac_addr);
+ struct efi_device_path_mac_addr *mdp =
+ (struct efi_device_path_mac_addr *)dp;
+
+ if (mdp->if_type <= 1)
+ n = 6;
+ s += sprintf(s, "MAC(");
+ for (i = 0; i < n; ++i)
+ s += sprintf(s, "%02x", mdp->mac.addr[i]);
+ s += sprintf(s, ",%u)", mdp->if_type);
+
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: {
+ struct efi_device_path_usb_class *ucdp =
+ (struct efi_device_path_usb_class *)dp;
+
+ s += sprintf(s, "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
+ ucdp->vendor_id, ucdp->product_id,
+ ucdp->device_class, ucdp->device_subclass,
+ ucdp->device_protocol);
+
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_NVME: {
+ struct efi_device_path_nvme *ndp =
+ (struct efi_device_path_nvme *)dp;
+ u32 ns_id;
+ int i;
+
+ memcpy(&ns_id, &ndp->ns_id, sizeof(ns_id));
+ s += sprintf(s, "NVMe(0x%x,", ns_id);
+ for (i = 0; i < sizeof(ndp->eui64); ++i)
+ s += sprintf(s, "%s%02x", i ? "-" : "",
+ ndp->eui64[i]);
+ s += sprintf(s, ")");
+
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_MSG_SD:
+ case DEVICE_PATH_SUB_TYPE_MSG_MMC: {
+ const char *typename =
+ (dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ?
+ "SD" : "eMMC";
+ struct efi_device_path_sd_mmc_path *sddp =
+ (struct efi_device_path_sd_mmc_path *)dp;
+ s += sprintf(s, "%s(%u)", typename, sddp->slot_number);
+ break;
+ }
+ default:
+ s = dp_unknown(s, dp);
+ break;
+ }
+ return s;
+}
+
+/*
+ * Convert a media device path node to text.
+ *
+ * @s output buffer
+ * @dp device path node
+ * @return next unused buffer address
+ */
+static char *dp_media(char *s, struct efi_device_path *dp)
+{
+ switch (dp->sub_type) {
+ case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: {
+ struct efi_device_path_hard_drive_path *hddp =
+ (struct efi_device_path_hard_drive_path *)dp;
+ void *sig = hddp->partition_signature;
+ u64 start;
+ u64 end;
+
+ /* Copy from packed structure to aligned memory */
+ memcpy(&start, &hddp->partition_start, sizeof(start));
+ memcpy(&end, &hddp->partition_end, sizeof(end));
+
+ switch (hddp->signature_type) {
+ case SIG_TYPE_MBR: {
+ u32 signature;
+
+ memcpy(&signature, sig, sizeof(signature));
+ s += sprintf(
+ s, "HD(%d,MBR,0x%08x,0x%llx,0x%llx)",
+ hddp->partition_number, signature, start, end);
+ break;
+ }
+ case SIG_TYPE_GUID:
+ s += sprintf(
+ s, "HD(%d,GPT,%pUl,0x%llx,0x%llx)",
+ hddp->partition_number, sig, start, end);
+ break;
+ default:
+ s += sprintf(
+ s, "HD(%d,0x%02x,0,0x%llx,0x%llx)",
+ hddp->partition_number, hddp->partmap_type,
+ start, end);
+ break;
+ }
+
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_CDROM_PATH: {
+ struct efi_device_path_cdrom_path *cddp =
+ (struct efi_device_path_cdrom_path *)dp;
+ s += sprintf(s, "CDROM(%u,0x%llx,0x%llx)", cddp->boot_entry,
+ cddp->partition_start, cddp->partition_size);
+ break;
+ }
+ case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
+ struct efi_device_path_file_path *fp =
+ (struct efi_device_path_file_path *)dp;
+ int slen = (dp->length - sizeof(*dp)) / 2;
+ if (slen > MAX_NODE_LEN - 2)
+ slen = MAX_NODE_LEN - 2;
+ s += sprintf(s, "%-.*ls", slen, fp->str);
+ break;
+ }
+ default:
+ s = dp_unknown(s, dp);
+ break;
+ }
+ return s;
+}
+
+/*
+ * Converts a single node to a char string.
+ *
+ * @buffer output buffer
+ * @dp device path or node
+ * @return end of string
+ */
+static char *efi_convert_single_device_node_to_text(
+ char *buffer,
+ struct efi_device_path *dp)
+{
+ char *str = buffer;
+
+ switch (dp->type) {
+ case DEVICE_PATH_TYPE_HARDWARE_DEVICE:
+ str = dp_hardware(str, dp);
+ break;
+ case DEVICE_PATH_TYPE_ACPI_DEVICE:
+ str = dp_acpi(str, dp);
+ break;
+ case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
+ str = dp_msging(str, dp);
+ break;
+ case DEVICE_PATH_TYPE_MEDIA_DEVICE:
+ str = dp_media(str, dp);
+ break;
+ case DEVICE_PATH_TYPE_END:
+ break;
+ default:
+ str = dp_unknown(str, dp);
+ }
+
+ *str = '\0';
+ return str;
+}
+
+/*
+ * This function implements the ConvertDeviceNodeToText service of the
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * device_node device node to be converted
+ * display_only true if the shorter text representation shall be used
+ * allow_shortcuts true if shortcut forms may be used
+ * @return text representation of the device path
+ * NULL if out of memory of device_path is NULL
+ */
+static uint16_t EFIAPI *efi_convert_device_node_to_text(
+ struct efi_device_path *device_node,
+ bool display_only,
+ bool allow_shortcuts)
+{
+ char str[MAX_NODE_LEN];
+ uint16_t *text = NULL;
+
+ EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
+
+ if (!device_node)
+ goto out;
+ efi_convert_single_device_node_to_text(str, device_node);
+
+ text = efi_str_to_u16(str);
+
+out:
+ EFI_EXIT(EFI_SUCCESS);
+ return text;
+}
+
+/*
+ * This function implements the ConvertDevicePathToText service of the
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * device_path device path to be converted
+ * display_only true if the shorter text representation shall be used
+ * allow_shortcuts true if shortcut forms may be used
+ * @return text representation of the device path
+ * NULL if out of memory of device_path is NULL
+ */
+static uint16_t EFIAPI *efi_convert_device_path_to_text(
+ struct efi_device_path *device_path,
+ bool display_only,
+ bool allow_shortcuts)
+{
+ uint16_t *text = NULL;
+ char buffer[MAX_PATH_LEN];
+ char *str = buffer;
+
+ EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
+
+ if (!device_path)
+ goto out;
+ while (device_path &&
+ str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) {
+ *str++ = '/';
+ str = efi_convert_single_device_node_to_text(str, device_path);
+ device_path = efi_dp_next(device_path);
+ }
+
+ text = efi_str_to_u16(buffer);
+
+out:
+ EFI_EXIT(EFI_SUCCESS);
+ return text;
+}
+
+/* helper for debug prints.. efi_free_pool() the result. */
+uint16_t *efi_dp_str(struct efi_device_path *dp)
+{
+ return EFI_CALL(efi_convert_device_path_to_text(dp, true, true));
+}
+
+const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
+ .convert_device_node_to_text = efi_convert_device_node_to_text,
+ .convert_device_path_to_text = efi_convert_device_path_to_text,
+};
diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c
new file mode 100644
index 00000000..94015329
--- /dev/null
+++ b/lib/efi_loader/efi_device_path_utilities.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI device path interface
+ *
+ * Copyright (c) 2017 Leif Lindholm
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+
+const efi_guid_t efi_guid_device_path_utilities_protocol =
+ EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
+
+/*
+ * Get size of a device path.
+ *
+ * This function implements the GetDevicePathSize service of the device path
+ * utilities protocol. The device path length includes the end of path tag
+ * which may be an instance end.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path device path
+ * @return size in bytes
+ */
+static efi_uintn_t EFIAPI get_device_path_size(
+ const struct efi_device_path *device_path)
+{
+ efi_uintn_t sz = 0;
+
+ EFI_ENTRY("%pD", device_path);
+ /* size includes the END node: */
+ if (device_path)
+ sz = efi_dp_size(device_path) + sizeof(struct efi_device_path);
+ return EFI_EXIT(sz);
+}
+
+/*
+ * Duplicate a device path.
+ *
+ * This function implements the DuplicateDevicePath service of the device path
+ * utilities protocol.
+ *
+ * The UEFI spec does not indicate what happens to the end tag. We follow the
+ * EDK2 logic: In case the device path ends with an end of instance tag, the
+ * copy will also end with an end of instance tag.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path device path
+ * @return copy of the device path
+ */
+static struct efi_device_path * EFIAPI duplicate_device_path(
+ const struct efi_device_path *device_path)
+{
+ EFI_ENTRY("%pD", device_path);
+ return EFI_EXIT(efi_dp_dup(device_path));
+}
+
+/*
+ * Append device path.
+ *
+ * This function implements the AppendDevicePath service of the device path
+ * utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @src1 1st device path
+ * @src2 2nd device path
+ * @return concatenated device path
+ */
+static struct efi_device_path * EFIAPI append_device_path(
+ const struct efi_device_path *src1,
+ const struct efi_device_path *src2)
+{
+ EFI_ENTRY("%pD, %pD", src1, src2);
+ return EFI_EXIT(efi_dp_append(src1, src2));
+}
+
+/*
+ * Append device path node.
+ *
+ * This function implements the AppendDeviceNode service of the device path
+ * utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path device path
+ * @device_node device node
+ * @return concatenated device path
+ */
+static struct efi_device_path * EFIAPI append_device_node(
+ const struct efi_device_path *device_path,
+ const struct efi_device_path *device_node)
+{
+ EFI_ENTRY("%pD, %p", device_path, device_node);
+ return EFI_EXIT(efi_dp_append_node(device_path, device_node));
+}
+
+/*
+ * Append device path instance.
+ *
+ * This function implements the AppendDevicePathInstance service of the device
+ * path utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path 1st device path
+ * @device_path_instance 2nd device path
+ * @return concatenated device path
+ */
+static struct efi_device_path * EFIAPI append_device_path_instance(
+ const struct efi_device_path *device_path,
+ const struct efi_device_path *device_path_instance)
+{
+ EFI_ENTRY("%pD, %pD", device_path, device_path_instance);
+ return EFI_EXIT(efi_dp_append_instance(device_path,
+ device_path_instance));
+}
+
+/*
+ * Get next device path instance.
+ *
+ * This function implements the GetNextDevicePathInstance service of the device
+ * path utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path_instance next device path instance
+ * @device_path_instance_size size of the device path instance
+ * @return concatenated device path
+ */
+static struct efi_device_path * EFIAPI get_next_device_path_instance(
+ struct efi_device_path **device_path_instance,
+ efi_uintn_t *device_path_instance_size)
+{
+ EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size);
+ return EFI_EXIT(efi_dp_get_next_instance(device_path_instance,
+ device_path_instance_size));
+}
+
+/*
+ * Check if a device path contains more than one instance.
+ *
+ * This function implements the AppendDeviceNode service of the device path
+ * utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @device_path device path
+ * @device_node device node
+ * @return concatenated device path
+ */
+static bool EFIAPI is_device_path_multi_instance(
+ const struct efi_device_path *device_path)
+{
+ EFI_ENTRY("%pD", device_path);
+ return EFI_EXIT(efi_dp_is_multi_instance(device_path));
+}
+
+/*
+ * Create device node.
+ *
+ * This function implements the CreateDeviceNode service of the device path
+ * utilities protocol.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @node_type node type
+ * @node_sub_type node sub type
+ * @node_length node length
+ * @return device path node
+ */
+static struct efi_device_path * EFIAPI create_device_node(
+ uint8_t node_type, uint8_t node_sub_type, uint16_t node_length)
+{
+ EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length);
+ return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type,
+ node_length));
+}
+
+const struct efi_device_path_utilities_protocol efi_device_path_utilities = {
+ .get_device_path_size = get_device_path_size,
+ .duplicate_device_path = duplicate_device_path,
+ .append_device_path = append_device_path,
+ .append_device_node = append_device_node,
+ .append_device_path_instance = append_device_path_instance,
+ .get_next_device_path_instance = get_next_device_path_instance,
+ .is_device_path_multi_instance = is_device_path_multi_instance,
+ .create_device_node = create_device_node,
+};
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
new file mode 100644
index 00000000..ed7fb3f7
--- /dev/null
+++ b/lib/efi_loader/efi_disk.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application disk support
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <fs.h>
+#include <part.h>
+#include <malloc.h>
+
+const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+
+/**
+ * struct efi_disk_obj - EFI disk object
+ *
+ * @header: EFI object header
+ * @ops: EFI disk I/O protocol interface
+ * @ifname: interface name for block device
+ * @dev_index: device index of block device
+ * @media: block I/O media information
+ * @dp: device path to the block device
+ * @part: partition
+ * @volume: simple file system protocol of the partition
+ * @offset: offset into disk for simple partition
+ * @desc: internal block device descriptor
+ */
+struct efi_disk_obj {
+ struct efi_object header;
+ struct efi_block_io ops;
+ const char *ifname;
+ int dev_index;
+ struct efi_block_io_media media;
+ struct efi_device_path *dp;
+ unsigned int part;
+ struct efi_simple_file_system_protocol *volume;
+ lbaint_t offset;
+ struct blk_desc *desc;
+};
+
+/**
+ * efi_disk_reset() - reset block device
+ *
+ * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL.
+ *
+ * As U-Boot's block devices do not have a reset function simply return
+ * EFI_SUCCESS.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: pointer to the BLOCK_IO_PROTOCOL
+ * @extended_verification: extended verification
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
+ char extended_verification)
+{
+ EFI_ENTRY("%p, %x", this, extended_verification);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+enum efi_disk_direction {
+ EFI_DISK_READ,
+ EFI_DISK_WRITE,
+};
+
+static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
+ u32 media_id, u64 lba, unsigned long buffer_size,
+ void *buffer, enum efi_disk_direction direction)
+{
+ struct efi_disk_obj *diskobj;
+ struct blk_desc *desc;
+ int blksz;
+ int blocks;
+ unsigned long n;
+
+ diskobj = container_of(this, struct efi_disk_obj, ops);
+ desc = (struct blk_desc *) diskobj->desc;
+ blksz = desc->blksz;
+ blocks = buffer_size / blksz;
+ lba += diskobj->offset;
+
+ EFI_PRINT("blocks=%x lba=%llx blksz=%x dir=%d\n",
+ blocks, lba, blksz, direction);
+
+ /* We only support full block access */
+ if (buffer_size & (blksz - 1))
+ return EFI_BAD_BUFFER_SIZE;
+
+ if (direction == EFI_DISK_READ)
+ n = blk_dread(desc, lba, blocks, buffer);
+ else
+ n = blk_dwrite(desc, lba, blocks, buffer);
+
+ /* We don't do interrupts, so check for timers cooperatively */
+ efi_timer_check();
+
+ EFI_PRINT("n=%lx blocks=%x\n", n, blocks);
+
+ if (n != blocks)
+ return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
+ u32 media_id, u64 lba, efi_uintn_t buffer_size,
+ void *buffer)
+{
+ void *real_buffer = buffer;
+ efi_status_t r;
+
+ if (!this)
+ return EFI_INVALID_PARAMETER;
+ /* TODO: check for media changes */
+ if (media_id != this->media->media_id)
+ return EFI_MEDIA_CHANGED;
+ if (!this->media->media_present)
+ return EFI_NO_MEDIA;
+ /* media->io_align is a power of 2 */
+ if ((uintptr_t)buffer & (this->media->io_align - 1))
+ return EFI_INVALID_PARAMETER;
+ if (lba * this->media->block_size + buffer_size >
+ this->media->last_block * this->media->block_size)
+ return EFI_INVALID_PARAMETER;
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+ if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
+ r = efi_disk_read_blocks(this, media_id, lba,
+ EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
+ if (r != EFI_SUCCESS)
+ return r;
+ return efi_disk_read_blocks(this, media_id, lba +
+ EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
+ buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
+ buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
+ }
+
+ real_buffer = efi_bounce_buffer;
+#endif
+
+ EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
+ buffer_size, buffer);
+
+ r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
+ EFI_DISK_READ);
+
+ /* Copy from bounce buffer to real buffer if necessary */
+ if ((r == EFI_SUCCESS) && (real_buffer != buffer))
+ memcpy(buffer, real_buffer, buffer_size);
+
+ return EFI_EXIT(r);
+}
+
+static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
+ u32 media_id, u64 lba, efi_uintn_t buffer_size,
+ void *buffer)
+{
+ void *real_buffer = buffer;
+ efi_status_t r;
+
+ if (!this)
+ return EFI_INVALID_PARAMETER;
+ if (this->media->read_only)
+ return EFI_WRITE_PROTECTED;
+ /* TODO: check for media changes */
+ if (media_id != this->media->media_id)
+ return EFI_MEDIA_CHANGED;
+ if (!this->media->media_present)
+ return EFI_NO_MEDIA;
+ /* media->io_align is a power of 2 */
+ if ((uintptr_t)buffer & (this->media->io_align - 1))
+ return EFI_INVALID_PARAMETER;
+ if (lba * this->media->block_size + buffer_size >
+ this->media->last_block * this->media->block_size)
+ return EFI_INVALID_PARAMETER;
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+ if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
+ r = efi_disk_write_blocks(this, media_id, lba,
+ EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
+ if (r != EFI_SUCCESS)
+ return r;
+ return efi_disk_write_blocks(this, media_id, lba +
+ EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
+ buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
+ buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
+ }
+
+ real_buffer = efi_bounce_buffer;
+#endif
+
+ EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba,
+ buffer_size, buffer);
+
+ /* Populate bounce buffer if necessary */
+ if (real_buffer != buffer)
+ memcpy(real_buffer, buffer, buffer_size);
+
+ r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
+ EFI_DISK_WRITE);
+
+ return EFI_EXIT(r);
+}
+
+static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
+{
+ /* We always write synchronously */
+ EFI_ENTRY("%p", this);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct efi_block_io block_io_disk_template = {
+ .reset = &efi_disk_reset,
+ .read_blocks = &efi_disk_read_blocks,
+ .write_blocks = &efi_disk_write_blocks,
+ .flush_blocks = &efi_disk_flush_blocks,
+};
+
+/*
+ * Get the simple file system protocol for a file device path.
+ *
+ * The full path provided is split into device part and into a file
+ * part. The device part is used to find the handle on which the
+ * simple file system protocol is installed.
+ *
+ * @full_path device path including device and file
+ * @return simple file system protocol
+ */
+struct efi_simple_file_system_protocol *
+efi_fs_from_path(struct efi_device_path *full_path)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+ struct efi_device_path *device_path;
+ struct efi_device_path *file_path;
+ efi_status_t ret;
+
+ /* Split the path into a device part and a file part */
+ ret = efi_dp_split_file_path(full_path, &device_path, &file_path);
+ if (ret != EFI_SUCCESS)
+ return NULL;
+ efi_free_pool(file_path);
+
+ /* Get the EFI object for the partition */
+ efiobj = efi_dp_find_obj(device_path, NULL);
+ efi_free_pool(device_path);
+ if (!efiobj)
+ return NULL;
+
+ /* Find the simple file system protocol */
+ ret = efi_search_protocol(efiobj, &efi_simple_file_system_protocol_guid,
+ &handler);
+ if (ret != EFI_SUCCESS)
+ return NULL;
+
+ /* Return the simple file system protocol for the partition */
+ return handler->protocol_interface;
+}
+
+/**
+ * efi_fs_exists() - check if a partition bears a file system
+ *
+ * @desc: block device descriptor
+ * @part: partition number
+ * Return: 1 if a file system exists on the partition
+ * 0 otherwise
+ */
+static int efi_fs_exists(struct blk_desc *desc, int part)
+{
+ if (fs_set_blk_dev_with_part(desc, part))
+ return 0;
+
+ if (fs_get_type() == FS_TYPE_ANY)
+ return 0;
+
+ fs_close();
+
+ return 1;
+}
+
+/*
+ * Create a handle for a partition or disk
+ *
+ * @parent parent handle
+ * @dp_parent parent device path
+ * @if_typename interface name for block device
+ * @desc internal block device
+ * @dev_index device index for block device
+ * @offset offset into disk for simple partitions
+ * @return disk object
+ */
+static efi_status_t efi_disk_add_dev(
+ efi_handle_t parent,
+ struct efi_device_path *dp_parent,
+ const char *if_typename,
+ struct blk_desc *desc,
+ int dev_index,
+ lbaint_t offset,
+ unsigned int part,
+ struct efi_disk_obj **disk)
+{
+ struct efi_disk_obj *diskobj;
+ efi_status_t ret;
+
+ /* Don't add empty devices */
+ if (!desc->lba)
+ return EFI_NOT_READY;
+
+ diskobj = calloc(1, sizeof(*diskobj));
+ if (!diskobj)
+ return EFI_OUT_OF_RESOURCES;
+
+ /* Hook up to the device list */
+ efi_add_handle(&diskobj->header);
+
+ /* Fill in object data */
+ if (part) {
+ struct efi_device_path *node = efi_dp_part_node(desc, part);
+
+ diskobj->dp = efi_dp_append_node(dp_parent, node);
+ efi_free_pool(node);
+ } else {
+ diskobj->dp = efi_dp_from_part(desc, part);
+ }
+ diskobj->part = part;
+ ret = efi_add_protocol(&diskobj->header, &efi_block_io_guid,
+ &diskobj->ops);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ ret = efi_add_protocol(&diskobj->header, &efi_guid_device_path,
+ diskobj->dp);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ /* partitions or whole disk without partitions */
+ if ((part || desc->part_type == PART_TYPE_UNKNOWN) &&
+ efi_fs_exists(desc, part)) {
+ diskobj->volume = efi_simple_file_system(desc, part,
+ diskobj->dp);
+ ret = efi_add_protocol(&diskobj->header,
+ &efi_simple_file_system_protocol_guid,
+ diskobj->volume);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ diskobj->ops = block_io_disk_template;
+ diskobj->ifname = if_typename;
+ diskobj->dev_index = dev_index;
+ diskobj->offset = offset;
+ diskobj->desc = desc;
+
+ /* Fill in EFI IO Media info (for read/write callbacks) */
+ diskobj->media.removable_media = desc->removable;
+ diskobj->media.media_present = 1;
+ /*
+ * MediaID is just an arbitrary counter.
+ * We have to change it if the medium is removed or changed.
+ */
+ diskobj->media.media_id = 1;
+ diskobj->media.block_size = desc->blksz;
+ diskobj->media.io_align = desc->blksz;
+ diskobj->media.last_block = desc->lba - offset;
+ if (part != 0)
+ diskobj->media.logical_partition = 1;
+ diskobj->ops.media = &diskobj->media;
+ if (disk)
+ *disk = diskobj;
+ return EFI_SUCCESS;
+}
+
+/*
+ * Create handles and protocols for the partitions of a block device
+ *
+ * @parent handle of the parent disk
+ * @blk_desc block device
+ * @if_typename interface type
+ * @diskid device number
+ * @pdevname device name
+ * @return number of partitions created
+ */
+int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
+ const char *if_typename, int diskid,
+ const char *pdevname)
+{
+ int disks = 0;
+ char devname[32] = { 0 }; /* dp->str is u16[32] long */
+ disk_partition_t info;
+ int part;
+ struct efi_device_path *dp = NULL;
+ efi_status_t ret;
+ struct efi_handler *handler;
+
+ /* Get the device path of the parent */
+ ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
+ if (ret == EFI_SUCCESS)
+ dp = handler->protocol_interface;
+
+ /* Add devices for each partition */
+ for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
+ if (part_get_info(desc, part, &info))
+ continue;
+ snprintf(devname, sizeof(devname), "%s:%d", pdevname,
+ part);
+ ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
+ info.start, part, NULL);
+ if (ret != EFI_SUCCESS) {
+ printf("Adding partition %s failed\n", pdevname);
+ continue;
+ }
+ disks++;
+ }
+
+ return disks;
+}
+
+/*
+ * U-Boot doesn't have a list of all online disk devices. So when running our
+ * EFI payload, we scan through all of the potentially available ones and
+ * store them in our object pool.
+ *
+ * TODO(sjg@chromium.org): Actually with CONFIG_BLK, U-Boot does have this.
+ * Consider converting the code to look up devices as needed. The EFI device
+ * could be a child of the UCLASS_BLK block device, perhaps.
+ *
+ * This gets called from do_bootefi_exec().
+ */
+efi_status_t efi_disk_register(void)
+{
+ struct efi_disk_obj *disk;
+ int disks = 0;
+ efi_status_t ret;
+#ifdef CONFIG_BLK
+ struct udevice *dev;
+
+ for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
+ uclass_next_device_check(&dev)) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+ const char *if_typename = blk_get_if_type_name(desc->if_type);
+
+ /* Add block device for the full device */
+ printf("Scanning disk %s...\n", dev->name);
+ ret = efi_disk_add_dev(NULL, NULL, if_typename,
+ desc, desc->devnum, 0, 0, &disk);
+ if (ret == EFI_NOT_READY) {
+ printf("Disk %s not ready\n", dev->name);
+ continue;
+ }
+ if (ret) {
+ printf("ERROR: failure to add disk device %s, r = %lu\n",
+ dev->name, ret & ~EFI_ERROR_MASK);
+ return ret;
+ }
+ disks++;
+
+ /* Partitions show up as block devices in EFI */
+ disks += efi_disk_create_partitions(
+ &disk->header, desc, if_typename,
+ desc->devnum, dev->name);
+ }
+#else
+ int i, if_type;
+
+ /* Search for all available disk devices */
+ for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) {
+ const struct blk_driver *cur_drvr;
+ const char *if_typename;
+
+ cur_drvr = blk_driver_lookup_type(if_type);
+ if (!cur_drvr)
+ continue;
+
+ if_typename = cur_drvr->if_typename;
+ printf("Scanning disks on %s...\n", if_typename);
+ for (i = 0; i < 4; i++) {
+ struct blk_desc *desc;
+ char devname[32] = { 0 }; /* dp->str is u16[32] long */
+
+ desc = blk_get_devnum_by_type(if_type, i);
+ if (!desc)
+ continue;
+ if (desc->type == DEV_TYPE_UNKNOWN)
+ continue;
+
+ snprintf(devname, sizeof(devname), "%s%d",
+ if_typename, i);
+
+ /* Add block device for the full device */
+ ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
+ i, 0, 0, &disk);
+ if (ret == EFI_NOT_READY) {
+ printf("Disk %s not ready\n", devname);
+ continue;
+ }
+ if (ret) {
+ printf("ERROR: failure to add disk device %s, r = %lu\n",
+ devname, ret & ~EFI_ERROR_MASK);
+ return ret;
+ }
+ disks++;
+
+ /* Partitions show up as block devices in EFI */
+ disks += efi_disk_create_partitions
+ (&disk->header, desc,
+ if_typename, i, devname);
+ }
+ }
+#endif
+ printf("Found %d disks\n", disks);
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
new file mode 100644
index 00000000..6d3f680e
--- /dev/null
+++ b/lib/efi_loader/efi_file.c
@@ -0,0 +1,883 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI_FILE_PROTOCOL
+ *
+ * Copyright (c) 2017 Rob Clark
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <fs.h>
+
+/* GUID for file system information */
+const efi_guid_t efi_file_system_info_guid = EFI_FILE_SYSTEM_INFO_GUID;
+
+/* GUID to obtain the volume label */
+const efi_guid_t efi_system_volume_label_id = EFI_FILE_SYSTEM_VOLUME_LABEL_ID;
+
+struct file_system {
+ struct efi_simple_file_system_protocol base;
+ struct efi_device_path *dp;
+ struct blk_desc *desc;
+ int part;
+};
+#define to_fs(x) container_of(x, struct file_system, base)
+
+struct file_handle {
+ struct efi_file_handle base;
+ struct file_system *fs;
+ loff_t offset; /* current file position/cursor */
+ int isdir;
+ u64 open_mode;
+
+ /* for reading a directory: */
+ struct fs_dir_stream *dirs;
+ struct fs_dirent *dent;
+
+ char path[0];
+};
+#define to_fh(x) container_of(x, struct file_handle, base)
+
+static const struct efi_file_handle efi_file_handle_protocol;
+
+static char *basename(struct file_handle *fh)
+{
+ char *s = strrchr(fh->path, '/');
+ if (s)
+ return s + 1;
+ return fh->path;
+}
+
+static int set_blk_dev(struct file_handle *fh)
+{
+ return fs_set_blk_dev_with_part(fh->fs->desc, fh->fs->part);
+}
+
+/**
+ * is_dir() - check if file handle points to directory
+ *
+ * We assume that set_blk_dev(fh) has been called already.
+ *
+ * @fh: file handle
+ * Return: true if file handle points to a directory
+ */
+static int is_dir(struct file_handle *fh)
+{
+ struct fs_dir_stream *dirs;
+
+ dirs = fs_opendir(fh->path);
+ if (!dirs)
+ return 0;
+
+ fs_closedir(dirs);
+
+ return 1;
+}
+
+/*
+ * Normalize a path which may include either back or fwd slashes,
+ * double slashes, . or .. entries in the path, etc.
+ */
+static int sanitize_path(char *path)
+{
+ char *p;
+
+ /* backslash to slash: */
+ p = path;
+ while ((p = strchr(p, '\\')))
+ *p++ = '/';
+
+ /* handle double-slashes: */
+ p = path;
+ while ((p = strstr(p, "//"))) {
+ char *src = p + 1;
+ memmove(p, src, strlen(src) + 1);
+ }
+
+ /* handle extra /.'s */
+ p = path;
+ while ((p = strstr(p, "/."))) {
+ /*
+ * You'd be tempted to do this *after* handling ".."s
+ * below to avoid having to check if "/." is start of
+ * a "/..", but that won't have the correct results..
+ * for example, "/foo/./../bar" would get resolved to
+ * "/foo/bar" if you did these two passes in the other
+ * order
+ */
+ if (p[2] == '.') {
+ p += 2;
+ continue;
+ }
+ char *src = p + 2;
+ memmove(p, src, strlen(src) + 1);
+ }
+
+ /* handle extra /..'s: */
+ p = path;
+ while ((p = strstr(p, "/.."))) {
+ char *src = p + 3;
+
+ p--;
+
+ /* find beginning of previous path entry: */
+ while (true) {
+ if (p < path)
+ return -1;
+ if (*p == '/')
+ break;
+ p--;
+ }
+
+ memmove(p, src, strlen(src) + 1);
+ }
+
+ return 0;
+}
+
+/**
+ * efi_create_file() - create file or directory
+ *
+ * @fh: file handle
+ * @attributes: attributes for newly created file
+ * Returns: 0 for success
+ */
+static int efi_create_file(struct file_handle *fh, u64 attributes)
+{
+ loff_t actwrite;
+ void *buffer = &actwrite;
+
+ if (attributes & EFI_FILE_DIRECTORY)
+ return fs_mkdir(fh->path);
+ else
+ return fs_write(fh->path, map_to_sysmem(buffer), 0, 0,
+ &actwrite);
+}
+
+/**
+ * file_open() - open a file handle
+ *
+ * @fs: file system
+ * @parent: directory relative to which the file is to be opened
+ * @file_name: path of the file to be opened. '\', '.', or '..' may
+ * be used as modifiers. A leading backslash indicates an
+ * absolute path.
+ * @open_mode: bit mask indicating the access mode (read, write,
+ * create)
+ * @attributes: attributes for newly created file
+ * Returns: handle to the opened file or NULL
+ */
+static struct efi_file_handle *file_open(struct file_system *fs,
+ struct file_handle *parent, u16 *file_name, u64 open_mode,
+ u64 attributes)
+{
+ struct file_handle *fh;
+ char f0[MAX_UTF8_PER_UTF16] = {0};
+ int plen = 0;
+ int flen = 0;
+
+ if (file_name) {
+ utf16_to_utf8((u8 *)f0, file_name, 1);
+ flen = u16_strlen(file_name);
+ }
+
+ /* we could have a parent, but also an absolute path: */
+ if (f0[0] == '\\') {
+ plen = 0;
+ } else if (parent) {
+ plen = strlen(parent->path) + 1;
+ }
+
+ /* +2 is for null and '/' */
+ fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
+
+ fh->open_mode = open_mode;
+ fh->base = efi_file_handle_protocol;
+ fh->fs = fs;
+
+ if (parent) {
+ char *p = fh->path;
+ int exists;
+
+ if (plen > 0) {
+ strcpy(p, parent->path);
+ p += plen - 1;
+ *p++ = '/';
+ }
+
+ utf16_to_utf8((u8 *)p, file_name, flen);
+
+ if (sanitize_path(fh->path))
+ goto error;
+
+ /* check if file exists: */
+ if (set_blk_dev(fh))
+ goto error;
+
+ exists = fs_exists(fh->path);
+ /* fs_exists() calls fs_close(), so open file system again */
+ if (set_blk_dev(fh))
+ goto error;
+
+ if (!exists) {
+ if (!(open_mode & EFI_FILE_MODE_CREATE) ||
+ efi_create_file(fh, attributes))
+ goto error;
+ if (set_blk_dev(fh))
+ goto error;
+ }
+
+ /* figure out if file is a directory: */
+ fh->isdir = is_dir(fh);
+ } else {
+ fh->isdir = 1;
+ strcpy(fh->path, "");
+ }
+
+ return &fh->base;
+
+error:
+ free(fh);
+ return NULL;
+}
+
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
+ file_name, open_mode, attributes);
+
+ /* Check parameters */
+ if (!file || !new_handle || !file_name) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (open_mode != EFI_FILE_MODE_READ &&
+ open_mode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE) &&
+ open_mode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
+ EFI_FILE_MODE_CREATE)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ /*
+ * The UEFI spec requires that attributes are only set in create mode.
+ * The SCT does not care about this and sets EFI_FILE_DIRECTORY in
+ * read mode. EDK2 does not check that attributes are zero if not in
+ * create mode.
+ *
+ * So here we only check attributes in create mode and do not check
+ * that they are zero otherwise.
+ */
+ if ((open_mode & EFI_FILE_MODE_CREATE) &&
+ (attributes & (EFI_FILE_READ_ONLY | ~EFI_FILE_VALID_ATTR))) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Open file */
+ *new_handle = file_open(fh->fs, fh, file_name, open_mode, attributes);
+ if (*new_handle) {
+ EFI_PRINT("file handle %p\n", *new_handle);
+ ret = EFI_SUCCESS;
+ } else {
+ ret = EFI_NOT_FOUND;
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t file_close(struct file_handle *fh)
+{
+ fs_closedir(fh->dirs);
+ free(fh);
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
+{
+ struct file_handle *fh = to_fh(file);
+ EFI_ENTRY("%p", file);
+ return EFI_EXIT(file_close(fh));
+}
+
+static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p", file);
+
+ if (set_blk_dev(fh) || fs_unlink(fh->path))
+ ret = EFI_WARN_DELETE_FAILURE;
+
+ file_close(fh);
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_get_file_size() - determine the size of a file
+ *
+ * @fh: file handle
+ * @file_size: pointer to receive file size
+ * Return: status code
+ */
+static efi_status_t efi_get_file_size(struct file_handle *fh,
+ loff_t *file_size)
+{
+ if (set_blk_dev(fh))
+ return EFI_DEVICE_ERROR;
+
+ if (fs_size(fh->path, file_size))
+ return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
+ void *buffer)
+{
+ loff_t actread;
+ efi_status_t ret;
+ loff_t file_size;
+
+ ret = efi_get_file_size(fh, &file_size);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (file_size < fh->offset) {
+ ret = EFI_DEVICE_ERROR;
+ return ret;
+ }
+
+ if (set_blk_dev(fh))
+ return EFI_DEVICE_ERROR;
+ if (fs_read(fh->path, map_to_sysmem(buffer), fh->offset,
+ *buffer_size, &actread))
+ return EFI_DEVICE_ERROR;
+
+ *buffer_size = actread;
+ fh->offset += actread;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
+ void *buffer)
+{
+ struct efi_file_info *info = buffer;
+ struct fs_dirent *dent;
+ u64 required_size;
+ u16 *dst;
+
+ if (set_blk_dev(fh))
+ return EFI_DEVICE_ERROR;
+
+ if (!fh->dirs) {
+ assert(fh->offset == 0);
+ fh->dirs = fs_opendir(fh->path);
+ if (!fh->dirs)
+ return EFI_DEVICE_ERROR;
+ fh->dent = NULL;
+ }
+
+ /*
+ * So this is a bit awkward. Since fs layer is stateful and we
+ * can't rewind an entry, in the EFI_BUFFER_TOO_SMALL case below
+ * we might have to return without consuming the dent.. so we
+ * have to stash it for next call.
+ */
+ if (fh->dent) {
+ dent = fh->dent;
+ } else {
+ dent = fs_readdir(fh->dirs);
+ }
+
+ if (!dent) {
+ /* no more files in directory */
+ *buffer_size = 0;
+ return EFI_SUCCESS;
+ }
+
+ /* check buffer size: */
+ required_size = sizeof(*info) +
+ 2 * (utf8_utf16_strlen(dent->name) + 1);
+ if (*buffer_size < required_size) {
+ *buffer_size = required_size;
+ fh->dent = dent;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ fh->dent = NULL;
+
+ *buffer_size = required_size;
+ memset(info, 0, required_size);
+
+ info->size = required_size;
+ info->file_size = dent->size;
+ info->physical_size = dent->size;
+
+ if (dent->type == FS_DT_DIR)
+ info->attribute |= EFI_FILE_DIRECTORY;
+
+ dst = info->file_name;
+ utf8_utf16_strcpy(&dst, dent->name);
+
+ fh->offset++;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_SUCCESS;
+ u64 bs;
+
+ EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+ if (!buffer_size || !buffer) {
+ ret = EFI_INVALID_PARAMETER;
+ goto error;
+ }
+
+ bs = *buffer_size;
+ if (fh->isdir)
+ ret = dir_read(fh, &bs, buffer);
+ else
+ ret = file_read(fh, &bs, buffer);
+ if (bs <= SIZE_MAX)
+ *buffer_size = bs;
+ else
+ *buffer_size = SIZE_MAX;
+
+error:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_write() - write to file
+ *
+ * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @file: file handle
+ * @buffer_size: number of bytes to write
+ * @buffer: buffer with the bytes to write
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
+ efi_uintn_t *buffer_size,
+ void *buffer)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_SUCCESS;
+ loff_t actwrite;
+
+ EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+ if (!file || !buffer_size || !buffer) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (fh->isdir) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ if (!(fh->open_mode & EFI_FILE_MODE_WRITE)) {
+ ret = EFI_ACCESS_DENIED;
+ goto out;
+ }
+
+ if (!*buffer_size)
+ goto out;
+
+ if (set_blk_dev(fh)) {
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+ if (fs_write(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size,
+ &actwrite)) {
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+ *buffer_size = actwrite;
+ fh->offset += actwrite;
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_getpos() - get current position in file
+ *
+ * This function implements the GetPosition service of the EFI file protocol.
+ * See the UEFI spec for details.
+ *
+ * @file: file handle
+ * @pos: pointer to file position
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file,
+ u64 *pos)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct file_handle *fh = to_fh(file);
+
+ EFI_ENTRY("%p, %p", file, pos);
+
+ if (fh->isdir) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ *pos = fh->offset;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_setpos() - set current position in file
+ *
+ * This function implements the SetPosition service of the EFI file protocol.
+ * See the UEFI spec for details.
+ *
+ * @file: file handle
+ * @pos: new file position
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
+ u64 pos)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %llu", file, pos);
+
+ if (fh->isdir) {
+ if (pos != 0) {
+ ret = EFI_UNSUPPORTED;
+ goto error;
+ }
+ fs_closedir(fh->dirs);
+ fh->dirs = NULL;
+ }
+
+ if (pos == ~0ULL) {
+ loff_t file_size;
+
+ ret = efi_get_file_size(fh, &file_size);
+ if (ret != EFI_SUCCESS)
+ goto error;
+ pos = file_size;
+ }
+
+ fh->offset = pos;
+
+error:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file,
+ const efi_guid_t *info_type,
+ efi_uintn_t *buffer_size,
+ void *buffer)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_SUCCESS;
+ u16 *dst;
+
+ EFI_ENTRY("%p, %pUl, %p, %p", file, info_type, buffer_size, buffer);
+
+ if (!file || !info_type || !buffer_size ||
+ (*buffer_size && !buffer)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto error;
+ }
+
+ if (!guidcmp(info_type, &efi_file_info_guid)) {
+ struct efi_file_info *info = buffer;
+ char *filename = basename(fh);
+ unsigned int required_size;
+ loff_t file_size;
+
+ /* check buffer size: */
+ required_size = sizeof(*info) +
+ 2 * (utf8_utf16_strlen(filename) + 1);
+ if (*buffer_size < required_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto error;
+ }
+
+ ret = efi_get_file_size(fh, &file_size);
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ memset(info, 0, required_size);
+
+ info->size = required_size;
+ info->file_size = file_size;
+ info->physical_size = file_size;
+
+ if (fh->isdir)
+ info->attribute |= EFI_FILE_DIRECTORY;
+
+ dst = info->file_name;
+ utf8_utf16_strcpy(&dst, filename);
+ } else if (!guidcmp(info_type, &efi_file_system_info_guid)) {
+ struct efi_file_system_info *info = buffer;
+ disk_partition_t part;
+ efi_uintn_t required_size;
+ int r;
+
+ if (fh->fs->part >= 1)
+ r = part_get_info(fh->fs->desc, fh->fs->part, &part);
+ else
+ r = part_get_info_whole_disk(fh->fs->desc, &part);
+ if (r < 0) {
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+ required_size = sizeof(*info) + 2;
+ if (*buffer_size < required_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto error;
+ }
+
+ memset(info, 0, required_size);
+
+ info->size = required_size;
+ info->read_only = true;
+ info->volume_size = part.size * part.blksz;
+ info->free_space = 0;
+ info->block_size = part.blksz;
+ /*
+ * TODO: The volume label is not available in U-Boot.
+ */
+ info->volume_label[0] = 0;
+ } else if (!guidcmp(info_type, &efi_system_volume_label_id)) {
+ if (*buffer_size < 2) {
+ *buffer_size = 2;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto error;
+ }
+ *(u16 *)buffer = 0;
+ } else {
+ ret = EFI_UNSUPPORTED;
+ }
+
+error:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file,
+ const efi_guid_t *info_type,
+ efi_uintn_t buffer_size,
+ void *buffer)
+{
+ struct file_handle *fh = to_fh(file);
+ efi_status_t ret = EFI_UNSUPPORTED;
+
+ EFI_ENTRY("%p, %pUl, %zu, %p", file, info_type, buffer_size, buffer);
+
+ if (!guidcmp(info_type, &efi_file_info_guid)) {
+ struct efi_file_info *info = (struct efi_file_info *)buffer;
+ char *filename = basename(fh);
+ char *new_file_name, *pos;
+ loff_t file_size;
+
+ /* The buffer will always contain a file name. */
+ if (buffer_size < sizeof(struct efi_file_info) + 2 ||
+ buffer_size < info->size) {
+ ret = EFI_BAD_BUFFER_SIZE;
+ goto out;
+ }
+ /* We cannot change the directory attribute */
+ if (!fh->isdir != !(info->attribute & EFI_FILE_DIRECTORY)) {
+ ret = EFI_ACCESS_DENIED;
+ goto out;
+ }
+ /* Check for renaming */
+ new_file_name = malloc(utf16_utf8_strlen(info->file_name));
+ if (!new_file_name) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ pos = new_file_name;
+ utf16_utf8_strcpy(&pos, info->file_name);
+ if (strcmp(new_file_name, filename)) {
+ /* TODO: we do not support renaming */
+ EFI_PRINT("Renaming not supported\n");
+ free(new_file_name);
+ ret = EFI_ACCESS_DENIED;
+ goto out;
+ }
+ free(new_file_name);
+ /* Check for truncation */
+ ret = efi_get_file_size(fh, &file_size);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ if (file_size != info->file_size) {
+ /* TODO: we do not support truncation */
+ EFI_PRINT("Truncation not supported\n");
+ ret = EFI_ACCESS_DENIED;
+ goto out;
+ }
+ /*
+ * We do not care for the other attributes
+ * TODO: Support read only
+ */
+ ret = EFI_SUCCESS;
+ } else {
+ /* TODO: We do not support changing the volume label */
+ ret = EFI_UNSUPPORTED;
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+{
+ EFI_ENTRY("%p", file);
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes,
+ struct efi_file_io_token *token)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
+ struct efi_file_io_token *token)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
+ struct efi_file_io_token *token)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
+ struct efi_file_io_token *token)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static const struct efi_file_handle efi_file_handle_protocol = {
+ .rev = EFI_FILE_PROTOCOL_REVISION2,
+ .open = efi_file_open,
+ .close = efi_file_close,
+ .delete = efi_file_delete,
+ .read = efi_file_read,
+ .write = efi_file_write,
+ .getpos = efi_file_getpos,
+ .setpos = efi_file_setpos,
+ .getinfo = efi_file_getinfo,
+ .setinfo = efi_file_setinfo,
+ .flush = efi_file_flush,
+ .open_ex = efi_file_open_ex,
+ .read_ex = efi_file_read_ex,
+ .write_ex = efi_file_write_ex,
+ .flush_ex = efi_file_flush_ex,
+};
+
+/**
+ * efi_file_from_path() - open file via device path
+ *
+ * @fp: device path
+ * @return: EFI_FILE_PROTOCOL for the file or NULL
+ */
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
+{
+ struct efi_simple_file_system_protocol *v;
+ struct efi_file_handle *f;
+ efi_status_t ret;
+
+ v = efi_fs_from_path(fp);
+ if (!v)
+ return NULL;
+
+ EFI_CALL(ret = v->open_volume(v, &f));
+ if (ret != EFI_SUCCESS)
+ return NULL;
+
+ /* Skip over device-path nodes before the file path. */
+ while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
+ fp = efi_dp_next(fp);
+
+ /*
+ * Step through the nodes of the directory path until the actual file
+ * node is reached which is the final node in the device path.
+ */
+ while (fp) {
+ struct efi_device_path_file_path *fdp =
+ container_of(fp, struct efi_device_path_file_path, dp);
+ struct efi_file_handle *f2;
+ u16 *filename;
+
+ if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) {
+ printf("bad file path!\n");
+ f->close(f);
+ return NULL;
+ }
+
+ filename = u16_strdup(fdp->str);
+ if (!filename)
+ return NULL;
+ EFI_CALL(ret = f->open(f, &f2, filename,
+ EFI_FILE_MODE_READ, 0));
+ free(filename);
+ if (ret != EFI_SUCCESS)
+ return NULL;
+
+ fp = efi_dp_next(fp);
+
+ EFI_CALL(f->close(f));
+ f = f2;
+ }
+
+ return f;
+}
+
+static efi_status_t EFIAPI
+efi_open_volume(struct efi_simple_file_system_protocol *this,
+ struct efi_file_handle **root)
+{
+ struct file_system *fs = to_fs(this);
+
+ EFI_ENTRY("%p, %p", this, root);
+
+ *root = file_open(fs, NULL, NULL, 0, 0);
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+struct efi_simple_file_system_protocol *
+efi_simple_file_system(struct blk_desc *desc, int part,
+ struct efi_device_path *dp)
+{
+ struct file_system *fs;
+
+ fs = calloc(1, sizeof(*fs));
+ fs->base.rev = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
+ fs->base.open_volume = efi_open_volume;
+ fs->desc = desc;
+ fs->part = part;
+ fs->dp = dp;
+
+ return &fs->base;
+}
diff --git a/lib/efi_loader/efi_freestanding.c b/lib/efi_loader/efi_freestanding.c
new file mode 100644
index 00000000..bd9da5bb
--- /dev/null
+++ b/lib/efi_loader/efi_freestanding.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Library for freestanding binary
+ *
+ * Copyright 2019, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * GCC requires that freestanding programs provide memcpy(), memmove(),
+ * memset(), and memcmp().
+ */
+
+#include <common.h>
+
+/**
+ * memcmp() - compare memory areas
+ *
+ * @s1: pointer to first area
+ * @s2: pointer to second area
+ * @n: number of bytes to compare
+ * Return: 0 if both memory areas are the same, otherwise the sign of the
+ * result value is the same as the sign of the difference between
+ * the first differing pair of bytes taken as u8.
+ */
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+ const u8 *pos1 = s1;
+ const u8 *pos2 = s2;
+
+ for (; n; --n) {
+ if (*pos1 != *pos2)
+ return *pos1 - *pos2;
+ ++pos1;
+ ++pos2;
+ }
+ return 0;
+}
+
+/**
+ * memcpy() - copy memory area
+ *
+ * @dest: destination buffer
+ * @src: source buffer
+ * @n: number of bytes to copy
+ * Return: pointer to destination buffer
+ */
+void *memmove(void *dest, const void *src, size_t n)
+{
+ u8 *d = dest;
+ const u8 *s = src;
+
+ if (d >= s) {
+ for (; n; --n)
+ *d++ = *s++;
+ } else {
+ d += n;
+ s += n;
+ for (; n; --n)
+ *--d = *--s;
+ }
+ return dest;
+}
+
+/**
+ * memcpy() - copy memory area
+ *
+ * @dest: destination buffer
+ * @src: source buffer
+ * @n: number of bytes to copy
+ * Return: pointer to destination buffer
+ */
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ return memmove(dest, src, n);
+}
+
+/**
+ * memset() - fill memory with a constant byte
+ *
+ * @s: destination buffer
+ * @c: byte value
+ * @n: number of bytes to set
+ * Return: pointer to destination buffer
+ */
+void *memset(void *s, int c, size_t n)
+{
+ u8 *d = s;
+
+ for (; n; --n)
+ *d++ = c;
+ return s;
+}
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
new file mode 100644
index 00000000..1511e3bd
--- /dev/null
+++ b/lib/efi_loader/efi_gop.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application disk support
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <lcd.h>
+#include <malloc.h>
+#include <video.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+
+/**
+ * struct efi_gop_obj - graphical output protocol object
+ *
+ * @header: EFI object header
+ * @ops: graphical output protocol interface
+ * @info: graphical output mode information
+ * @mode: graphical output mode
+ * @bpix: bits per pixel
+ * @fb: frame buffer
+ */
+struct efi_gop_obj {
+ struct efi_object header;
+ struct efi_gop ops;
+ struct efi_gop_mode_info info;
+ struct efi_gop_mode mode;
+ /* Fields we only have access to during init */
+ u32 bpix;
+ void *fb;
+};
+
+static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number,
+ efi_uintn_t *size_of_info,
+ struct efi_gop_mode_info **info)
+{
+ struct efi_gop_obj *gopobj;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info);
+
+ if (!this || !size_of_info || !info || mode_number) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ gopobj = container_of(this, struct efi_gop_obj, ops);
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, sizeof(gopobj->info),
+ (void **)info);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ *size_of_info = sizeof(gopobj->info);
+ memcpy(*info, &gopobj->info, sizeof(gopobj->info));
+
+out:
+ return EFI_EXIT(ret);
+}
+
+static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid)
+{
+ struct efi_gop_pixel blt = {
+ .reserved = 0,
+ };
+
+ blt.blue = (vid & 0x1f) << 3;
+ vid >>= 5;
+ blt.green = (vid & 0x3f) << 2;
+ vid >>= 6;
+ blt.red = (vid & 0x1f) << 3;
+ return blt;
+}
+
+static __always_inline u16 efi_blt_col_to_vid16(struct efi_gop_pixel *blt)
+{
+ return (u16)(blt->red >> 3) << 11 |
+ (u16)(blt->green >> 2) << 5 |
+ (u16)(blt->blue >> 3);
+}
+
+static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
+ struct efi_gop_pixel *bufferp,
+ u32 operation, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy,
+ efi_uintn_t width,
+ efi_uintn_t height,
+ efi_uintn_t delta,
+ efi_uintn_t vid_bpp)
+{
+ struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops);
+ efi_uintn_t i, j, linelen, slineoff = 0, dlineoff, swidth, dwidth;
+ u32 *fb32 = gopobj->fb;
+ u16 *fb16 = gopobj->fb;
+ struct efi_gop_pixel *buffer = __builtin_assume_aligned(bufferp, 4);
+
+ if (delta) {
+ /* Check for 4 byte alignment */
+ if (delta & 3)
+ return EFI_INVALID_PARAMETER;
+ linelen = delta >> 2;
+ } else {
+ linelen = width;
+ }
+
+ /* Check source rectangle */
+ switch (operation) {
+ case EFI_BLT_VIDEO_FILL:
+ break;
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ if (sx + width > linelen)
+ return EFI_INVALID_PARAMETER;
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ if (sx + width > gopobj->info.width ||
+ sy + height > gopobj->info.height)
+ return EFI_INVALID_PARAMETER;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Check destination rectangle */
+ switch (operation) {
+ case EFI_BLT_VIDEO_FILL:
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ if (dx + width > gopobj->info.width ||
+ dy + height > gopobj->info.height)
+ return EFI_INVALID_PARAMETER;
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ if (dx + width > linelen)
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Calculate line width */
+ switch (operation) {
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ swidth = linelen;
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ swidth = gopobj->info.width;
+ if (!vid_bpp)
+ return EFI_UNSUPPORTED;
+ break;
+ case EFI_BLT_VIDEO_FILL:
+ swidth = 0;
+ break;
+ }
+
+ switch (operation) {
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ case EFI_BLT_VIDEO_FILL:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ dwidth = gopobj->info.width;
+ if (!vid_bpp)
+ return EFI_UNSUPPORTED;
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ dwidth = linelen;
+ break;
+ }
+
+ slineoff = swidth * sy;
+ dlineoff = dwidth * dy;
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ struct efi_gop_pixel pix;
+
+ /* Read source pixel */
+ switch (operation) {
+ case EFI_BLT_VIDEO_FILL:
+ pix = *buffer;
+ break;
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ pix = buffer[slineoff + j + sx];
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ if (vid_bpp == 32)
+ pix = *(struct efi_gop_pixel *)&fb32[
+ slineoff + j + sx];
+ else
+ pix = efi_vid16_to_blt_col(fb16[
+ slineoff + j + sx]);
+ break;
+ }
+
+ /* Write destination pixel */
+ switch (operation) {
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ buffer[dlineoff + j + dx] = pix;
+ break;
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ case EFI_BLT_VIDEO_FILL:
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ if (vid_bpp == 32)
+ fb32[dlineoff + j + dx] = *(u32 *)&pix;
+ else
+ fb16[dlineoff + j + dx] =
+ efi_blt_col_to_vid16(&pix);
+ break;
+ }
+ }
+ slineoff += swidth;
+ dlineoff += dwidth;
+ }
+
+ return EFI_SUCCESS;
+}
+
+static efi_uintn_t gop_get_bpp(struct efi_gop *this)
+{
+ struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops);
+ efi_uintn_t vid_bpp = 0;
+
+ switch (gopobj->bpix) {
+#ifdef CONFIG_DM_VIDEO
+ case VIDEO_BPP32:
+#else
+ case LCD_COLOR32:
+#endif
+ vid_bpp = 32;
+ break;
+#ifdef CONFIG_DM_VIDEO
+ case VIDEO_BPP16:
+#else
+ case LCD_COLOR16:
+#endif
+ vid_bpp = 16;
+ break;
+ }
+
+ return vid_bpp;
+}
+
+/*
+ * GCC can't optimize our BLT function well, but we need to make sure that
+ * our 2-dimensional loop gets executed very quickly, otherwise the system
+ * will feel slow.
+ *
+ * By manually putting all obvious branch targets into functions which call
+ * our generic BLT function with constants, the compiler can successfully
+ * optimize for speed.
+ */
+static efi_status_t gop_blt_video_fill(struct efi_gop *this,
+ struct efi_gop_pixel *buffer,
+ u32 foo, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta,
+ efi_uintn_t vid_bpp)
+{
+ return gop_blt_int(this, buffer, EFI_BLT_VIDEO_FILL, sx, sy, dx,
+ dy, width, height, delta, vid_bpp);
+}
+
+static efi_status_t gop_blt_buf_to_vid16(struct efi_gop *this,
+ struct efi_gop_pixel *buffer,
+ u32 foo, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta)
+{
+ return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
+ dy, width, height, delta, 16);
+}
+
+static efi_status_t gop_blt_buf_to_vid32(struct efi_gop *this,
+ struct efi_gop_pixel *buffer,
+ u32 foo, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta)
+{
+ return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
+ dy, width, height, delta, 32);
+}
+
+static efi_status_t gop_blt_vid_to_vid(struct efi_gop *this,
+ struct efi_gop_pixel *buffer,
+ u32 foo, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta,
+ efi_uintn_t vid_bpp)
+{
+ return gop_blt_int(this, buffer, EFI_BLT_VIDEO_TO_VIDEO, sx, sy, dx,
+ dy, width, height, delta, vid_bpp);
+}
+
+static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this,
+ struct efi_gop_pixel *buffer,
+ u32 foo, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta,
+ efi_uintn_t vid_bpp)
+{
+ return gop_blt_int(this, buffer, EFI_BLT_VIDEO_TO_BLT_BUFFER, sx, sy,
+ dx, dy, width, height, delta, vid_bpp);
+}
+
+/**
+ * gop_set_mode() - set graphical output mode
+ *
+ * This function implements the SetMode() service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: the graphical output protocol
+ * @mode_number: the mode to be set
+ * Return: status code
+ */
+static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
+{
+ struct efi_gop_obj *gopobj;
+ struct efi_gop_pixel buffer = {0, 0, 0, 0};
+ efi_uintn_t vid_bpp;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %x", this, mode_number);
+
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (mode_number) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ gopobj = container_of(this, struct efi_gop_obj, ops);
+ vid_bpp = gop_get_bpp(this);
+ ret = gop_blt_video_fill(this, &buffer, EFI_BLT_VIDEO_FILL, 0, 0, 0, 0,
+ gopobj->info.width, gopobj->info.height, 0,
+ vid_bpp);
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * Copy rectangle.
+ *
+ * This function implements the Blt service of the EFI_GRAPHICS_OUTPUT_PROTOCOL.
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: EFI_GRAPHICS_OUTPUT_PROTOCOL
+ * @buffer: pixel buffer
+ * @sx: source x-coordinate
+ * @sy: source y-coordinate
+ * @dx: destination x-coordinate
+ * @dy: destination y-coordinate
+ * @width: width of rectangle
+ * @height: height of rectangle
+ * @delta: length in bytes of a line in the pixel buffer (optional)
+ * @return: status code
+ */
+efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
+ u32 operation, efi_uintn_t sx,
+ efi_uintn_t sy, efi_uintn_t dx,
+ efi_uintn_t dy, efi_uintn_t width,
+ efi_uintn_t height, efi_uintn_t delta)
+{
+ efi_status_t ret = EFI_INVALID_PARAMETER;
+ efi_uintn_t vid_bpp;
+
+ EFI_ENTRY("%p, %p, %u, %zu, %zu, %zu, %zu, %zu, %zu, %zu", this,
+ buffer, operation, sx, sy, dx, dy, width, height, delta);
+
+ vid_bpp = gop_get_bpp(this);
+
+ /* Allow for compiler optimization */
+ switch (operation) {
+ case EFI_BLT_VIDEO_FILL:
+ ret = gop_blt_video_fill(this, buffer, operation, sx, sy, dx,
+ dy, width, height, delta, vid_bpp);
+ break;
+ case EFI_BLT_BUFFER_TO_VIDEO:
+ /* This needs to be super-fast, so duplicate for 16/32bpp */
+ if (vid_bpp == 32)
+ ret = gop_blt_buf_to_vid32(this, buffer, operation, sx,
+ sy, dx, dy, width, height,
+ delta);
+ else
+ ret = gop_blt_buf_to_vid16(this, buffer, operation, sx,
+ sy, dx, dy, width, height,
+ delta);
+ break;
+ case EFI_BLT_VIDEO_TO_VIDEO:
+ ret = gop_blt_vid_to_vid(this, buffer, operation, sx, sy, dx,
+ dy, width, height, delta, vid_bpp);
+ break;
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
+ ret = gop_blt_vid_to_buf(this, buffer, operation, sx, sy, dx,
+ dy, width, height, delta, vid_bpp);
+ break;
+ default:
+ ret = EFI_INVALID_PARAMETER;
+ }
+
+ if (ret != EFI_SUCCESS)
+ return EFI_EXIT(ret);
+
+#ifdef CONFIG_DM_VIDEO
+ video_sync_all();
+#else
+ lcd_sync();
+#endif
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/*
+ * Install graphical output protocol.
+ *
+ * If no supported video device exists this is not considered as an
+ * error.
+ */
+efi_status_t efi_gop_register(void)
+{
+ struct efi_gop_obj *gopobj;
+ u32 bpix, col, row;
+ u64 fb_base, fb_size;
+ void *fb;
+ efi_status_t ret;
+
+#ifdef CONFIG_DM_VIDEO
+ struct udevice *vdev;
+ struct video_priv *priv;
+
+ /* We only support a single video output device for now */
+ if (uclass_first_device(UCLASS_VIDEO, &vdev) || !vdev) {
+ debug("WARNING: No video device\n");
+ return EFI_SUCCESS;
+ }
+
+ priv = dev_get_uclass_priv(vdev);
+ bpix = priv->bpix;
+ col = video_get_xsize(vdev);
+ row = video_get_ysize(vdev);
+ fb_base = (uintptr_t)priv->fb;
+ fb_size = priv->fb_size;
+ fb = priv->fb;
+#else
+ int line_len;
+
+ bpix = panel_info.vl_bpix;
+ col = panel_info.vl_col;
+ row = panel_info.vl_row;
+ fb_base = gd->fb_base;
+ fb_size = lcd_get_size(&line_len);
+ fb = (void*)gd->fb_base;
+#endif
+
+ switch (bpix) {
+#ifdef CONFIG_DM_VIDEO
+ case VIDEO_BPP16:
+ case VIDEO_BPP32:
+#else
+ case LCD_COLOR32:
+ case LCD_COLOR16:
+#endif
+ break;
+ default:
+ /* So far, we only work in 16 or 32 bit mode */
+ debug("WARNING: Unsupported video mode\n");
+ return EFI_SUCCESS;
+ }
+
+ gopobj = calloc(1, sizeof(*gopobj));
+ if (!gopobj) {
+ printf("ERROR: Out of memory\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ /* Hook up to the device list */
+ efi_add_handle(&gopobj->header);
+
+ /* Fill in object data */
+ ret = efi_add_protocol(&gopobj->header, &efi_gop_guid,
+ &gopobj->ops);
+ if (ret != EFI_SUCCESS) {
+ printf("ERROR: Failure adding GOP protocol\n");
+ return ret;
+ }
+ gopobj->ops.query_mode = gop_query_mode;
+ gopobj->ops.set_mode = gop_set_mode;
+ gopobj->ops.blt = gop_blt;
+ gopobj->ops.mode = &gopobj->mode;
+
+ gopobj->mode.max_mode = 1;
+ gopobj->mode.info = &gopobj->info;
+ gopobj->mode.info_size = sizeof(gopobj->info);
+
+ gopobj->mode.fb_base = fb_base;
+ gopobj->mode.fb_size = fb_size;
+
+ gopobj->info.version = 0;
+ gopobj->info.width = col;
+ gopobj->info.height = row;
+#ifdef CONFIG_DM_VIDEO
+ if (bpix == VIDEO_BPP32)
+#else
+ if (bpix == LCD_COLOR32)
+#endif
+ {
+ gopobj->info.pixel_format = EFI_GOT_BGRA8;
+ } else {
+ gopobj->info.pixel_format = EFI_GOT_BITMASK;
+ gopobj->info.pixel_bitmask[0] = 0xf800; /* red */
+ gopobj->info.pixel_bitmask[1] = 0x07e0; /* green */
+ gopobj->info.pixel_bitmask[2] = 0x001f; /* blue */
+ }
+ gopobj->info.pixels_per_scanline = col;
+ gopobj->bpix = bpix;
+ gopobj->fb = fb;
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
new file mode 100644
index 00000000..77e33028
--- /dev/null
+++ b/lib/efi_loader/efi_hii.c
@@ -0,0 +1,1073 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI Human Interface Infrastructure ... database and packages
+ *
+ * Copyright (c) 2017 Leif Lindholm
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <asm/unaligned.h>
+
+const efi_guid_t efi_guid_hii_database_protocol
+ = EFI_HII_DATABASE_PROTOCOL_GUID;
+const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID;
+
+static LIST_HEAD(efi_package_lists);
+static LIST_HEAD(efi_keyboard_layout_list);
+
+struct efi_hii_packagelist {
+ struct list_head link;
+ // TODO should there be an associated efi_object?
+ efi_handle_t driver_handle;
+ u32 max_string_id;
+ struct list_head string_tables; /* list of efi_string_table */
+ struct list_head guid_list;
+ struct list_head keyboard_packages;
+
+ /* we could also track fonts, images, etc */
+};
+
+static int efi_hii_packagelist_exists(efi_hii_handle_t package_list)
+{
+ struct efi_hii_packagelist *hii;
+ int found = 0;
+
+ list_for_each_entry(hii, &efi_package_lists, link) {
+ if (hii == package_list) {
+ found = 1;
+ break;
+ }
+ }
+
+ return found;
+}
+
+static u32 efi_hii_package_type(struct efi_hii_package_header *header)
+{
+ u32 fields;
+
+ fields = get_unaligned_le32(&header->fields);
+
+ return (fields >> __EFI_HII_PACKAGE_TYPE_SHIFT)
+ & __EFI_HII_PACKAGE_TYPE_MASK;
+}
+
+static u32 efi_hii_package_len(struct efi_hii_package_header *header)
+{
+ u32 fields;
+
+ fields = get_unaligned_le32(&header->fields);
+
+ return (fields >> __EFI_HII_PACKAGE_LEN_SHIFT)
+ & __EFI_HII_PACKAGE_LEN_MASK;
+}
+
+struct efi_string_info {
+ efi_string_t string;
+ /* we could also track font info, etc */
+};
+
+struct efi_string_table {
+ struct list_head link;
+ efi_string_id_t language_name;
+ char *language;
+ u32 nstrings;
+ /*
+ * NOTE:
+ * string id starts at 1 so value is stbl->strings[id-1],
+ * and strings[] is a array of stbl->nstrings elements
+ */
+ struct efi_string_info *strings;
+};
+
+struct efi_guid_data {
+ struct list_head link;
+ struct efi_hii_guid_package package;
+};
+
+struct efi_keyboard_layout_data {
+ struct list_head link; /* in package */
+ struct list_head link_sys; /* in global list */
+ struct efi_hii_keyboard_layout keyboard_layout;
+};
+
+struct efi_keyboard_package_data {
+ struct list_head link; /* in package_list */
+ struct list_head keyboard_layout_list;
+};
+
+static void free_strings_table(struct efi_string_table *stbl)
+{
+ int i;
+
+ for (i = 0; i < stbl->nstrings; i++)
+ free(stbl->strings[i].string);
+ free(stbl->strings);
+ free(stbl->language);
+ free(stbl);
+}
+
+static void remove_strings_package(struct efi_hii_packagelist *hii)
+{
+ while (!list_empty(&hii->string_tables)) {
+ struct efi_string_table *stbl;
+
+ stbl = list_first_entry(&hii->string_tables,
+ struct efi_string_table, link);
+ list_del(&stbl->link);
+ free_strings_table(stbl);
+ }
+}
+
+static efi_status_t
+add_strings_package(struct efi_hii_packagelist *hii,
+ struct efi_hii_strings_package *strings_package)
+{
+ struct efi_hii_string_block *block;
+ void *end;
+ u32 nstrings = 0, idx = 0;
+ struct efi_string_table *stbl = NULL;
+ efi_status_t ret;
+
+ EFI_PRINT("header_size: %08x\n",
+ get_unaligned_le32(&strings_package->header_size));
+ EFI_PRINT("string_info_offset: %08x\n",
+ get_unaligned_le32(&strings_package->string_info_offset));
+ EFI_PRINT("language_name: %u\n",
+ get_unaligned_le16(&strings_package->language_name));
+ EFI_PRINT("language: %s\n", strings_package->language);
+
+ /* count # of string entries: */
+ end = ((void *)strings_package)
+ + efi_hii_package_len(&strings_package->header);
+ block = ((void *)strings_package)
+ + get_unaligned_le32(&strings_package->string_info_offset);
+
+ while ((void *)block < end) {
+ switch (block->block_type) {
+ case EFI_HII_SIBT_STRING_UCS2: {
+ struct efi_hii_sibt_string_ucs2_block *ucs2;
+
+ ucs2 = (void *)block;
+ nstrings++;
+ block = efi_hii_sibt_string_ucs2_block_next(ucs2);
+ break;
+ }
+ case EFI_HII_SIBT_END:
+ block = end;
+ break;
+ default:
+ EFI_PRINT("unknown HII string block type: %02x\n",
+ block->block_type);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ stbl = calloc(sizeof(*stbl), 1);
+ if (!stbl) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+ stbl->strings = calloc(sizeof(stbl->strings[0]), nstrings);
+ if (!stbl->strings) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+ stbl->language_name =
+ get_unaligned_le16(&strings_package->language_name);
+ stbl->language = strdup((char *)strings_package->language);
+ if (!stbl->language) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+ stbl->nstrings = nstrings;
+
+ /* and now parse string entries and populate efi_string_table */
+ block = ((void *)strings_package)
+ + get_unaligned_le32(&strings_package->string_info_offset);
+
+ while ((void *)block < end) {
+ switch (block->block_type) {
+ case EFI_HII_SIBT_STRING_UCS2: {
+ struct efi_hii_sibt_string_ucs2_block *ucs2;
+
+ ucs2 = (void *)block;
+ EFI_PRINT("%4u: \"%ls\"\n", idx + 1, ucs2->string_text);
+ stbl->strings[idx].string =
+ u16_strdup(ucs2->string_text);
+ if (!stbl->strings[idx].string) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+ idx++;
+ /* FIXME: accessing u16 * here */
+ block = efi_hii_sibt_string_ucs2_block_next(ucs2);
+ break;
+ }
+ case EFI_HII_SIBT_END:
+ goto out;
+ default:
+ EFI_PRINT("unknown HII string block type: %02x\n",
+ block->block_type);
+ ret = EFI_INVALID_PARAMETER;
+ goto error;
+ }
+ }
+
+out:
+ list_add(&stbl->link, &hii->string_tables);
+ if (hii->max_string_id < nstrings)
+ hii->max_string_id = nstrings;
+
+ return EFI_SUCCESS;
+
+error:
+ if (stbl) {
+ free(stbl->language);
+ while (idx > 0)
+ free(stbl->strings[--idx].string);
+ free(stbl->strings);
+ }
+ free(stbl);
+
+ return ret;
+}
+
+static void remove_guid_package(struct efi_hii_packagelist *hii)
+{
+ struct efi_guid_data *data;
+
+ while (!list_empty(&hii->guid_list)) {
+ data = list_first_entry(&hii->guid_list,
+ struct efi_guid_data, link);
+ list_del(&data->link);
+ free(data);
+ }
+}
+
+static efi_status_t
+add_guid_package(struct efi_hii_packagelist *hii,
+ struct efi_hii_guid_package *package)
+{
+ struct efi_guid_data *data;
+
+ data = calloc(sizeof(*data), 1);
+ if (!data)
+ return EFI_OUT_OF_RESOURCES;
+
+ /* TODO: we don't know any about data field */
+ memcpy(&data->package, package, sizeof(*package));
+ list_add_tail(&data->link, &hii->guid_list);
+
+ return EFI_SUCCESS;
+}
+
+static void free_keyboard_layouts(struct efi_keyboard_package_data *package)
+{
+ struct efi_keyboard_layout_data *layout_data;
+
+ while (!list_empty(&package->keyboard_layout_list)) {
+ layout_data = list_first_entry(&package->keyboard_layout_list,
+ struct efi_keyboard_layout_data,
+ link);
+ list_del(&layout_data->link);
+ list_del(&layout_data->link_sys);
+ free(layout_data);
+ }
+}
+
+static void remove_keyboard_package(struct efi_hii_packagelist *hii)
+{
+ struct efi_keyboard_package_data *package;
+
+ while (!list_empty(&hii->keyboard_packages)) {
+ package = list_first_entry(&hii->keyboard_packages,
+ struct efi_keyboard_package_data,
+ link);
+ free_keyboard_layouts(package);
+ list_del(&package->link);
+ free(package);
+ }
+}
+
+static efi_status_t
+add_keyboard_package(struct efi_hii_packagelist *hii,
+ struct efi_hii_keyboard_package *keyboard_package)
+{
+ struct efi_keyboard_package_data *package_data;
+ struct efi_hii_keyboard_layout *layout;
+ struct efi_keyboard_layout_data *layout_data;
+ u16 layout_count, layout_length;
+ int i;
+
+ package_data = malloc(sizeof(*package_data));
+ if (!package_data)
+ return EFI_OUT_OF_RESOURCES;
+ INIT_LIST_HEAD(&package_data->link);
+ INIT_LIST_HEAD(&package_data->keyboard_layout_list);
+
+ layout = &keyboard_package->layout[0];
+ layout_count = get_unaligned_le16(&keyboard_package->layout_count);
+ for (i = 0; i < layout_count; i++) {
+ layout_length = get_unaligned_le16(&layout->layout_length);
+ layout_data = malloc(sizeof(*layout_data) + layout_length);
+ if (!layout_data)
+ goto out;
+
+ memcpy(&layout_data->keyboard_layout, layout, layout_length);
+ list_add_tail(&layout_data->link,
+ &package_data->keyboard_layout_list);
+ list_add_tail(&layout_data->link_sys,
+ &efi_keyboard_layout_list);
+
+ layout += layout_length;
+ }
+
+ list_add_tail(&package_data->link, &hii->keyboard_packages);
+
+ return EFI_SUCCESS;
+
+out:
+ free_keyboard_layouts(package_data);
+ free(package_data);
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+static struct efi_hii_packagelist *new_packagelist(void)
+{
+ struct efi_hii_packagelist *hii;
+
+ hii = malloc(sizeof(*hii));
+ list_add_tail(&hii->link, &efi_package_lists);
+ hii->max_string_id = 0;
+ INIT_LIST_HEAD(&hii->string_tables);
+ INIT_LIST_HEAD(&hii->guid_list);
+ INIT_LIST_HEAD(&hii->keyboard_packages);
+
+ return hii;
+}
+
+static void free_packagelist(struct efi_hii_packagelist *hii)
+{
+ remove_strings_package(hii);
+ remove_guid_package(hii);
+ remove_keyboard_package(hii);
+
+ list_del(&hii->link);
+ free(hii);
+}
+
+static efi_status_t
+add_packages(struct efi_hii_packagelist *hii,
+ const struct efi_hii_package_list_header *package_list)
+{
+ struct efi_hii_package_header *package;
+ void *end;
+ efi_status_t ret = EFI_SUCCESS;
+
+ end = ((void *)package_list)
+ + get_unaligned_le32(&package_list->package_length);
+
+ EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid,
+ get_unaligned_le32(&package_list->package_length));
+
+ package = ((void *)package_list) + sizeof(*package_list);
+ while ((void *)package < end) {
+ EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
+ efi_hii_package_type(package),
+ efi_hii_package_len(package));
+
+ switch (efi_hii_package_type(package)) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ ret = add_guid_package(hii,
+ (struct efi_hii_guid_package *)package);
+ break;
+ case EFI_HII_PACKAGE_FORMS:
+ EFI_PRINT("Form package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ ret = add_strings_package(hii,
+ (struct efi_hii_strings_package *)package);
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ EFI_PRINT("Font package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ EFI_PRINT("Image package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ EFI_PRINT("Simple font package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ EFI_PRINT("Device path package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ ret = add_keyboard_package(hii,
+ (struct efi_hii_keyboard_package *)package);
+ break;
+ case EFI_HII_PACKAGE_ANIMATIONS:
+ EFI_PRINT("Animation package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_END:
+ goto out;
+ case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
+ case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
+ default:
+ break;
+ }
+
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ package = (void *)package + efi_hii_package_len(package);
+ }
+out:
+ // TODO in theory there is some notifications that should be sent..
+ return EFI_SUCCESS;
+}
+
+/*
+ * EFI_HII_DATABASE_PROTOCOL
+ */
+
+static efi_status_t EFIAPI
+new_package_list(const struct efi_hii_database_protocol *this,
+ const struct efi_hii_package_list_header *package_list,
+ const efi_handle_t driver_handle,
+ efi_hii_handle_t *handle)
+{
+ struct efi_hii_packagelist *hii;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, %p, %p", this, package_list, driver_handle, handle);
+
+ if (!package_list || !handle)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ hii = new_packagelist();
+ if (!hii)
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+ ret = add_packages(hii, package_list);
+ if (ret != EFI_SUCCESS) {
+ free_packagelist(hii);
+ return EFI_EXIT(ret);
+ }
+
+ hii->driver_handle = driver_handle;
+ *handle = hii;
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+remove_package_list(const struct efi_hii_database_protocol *this,
+ efi_hii_handle_t handle)
+{
+ struct efi_hii_packagelist *hii = handle;
+
+ EFI_ENTRY("%p, %p", this, handle);
+
+ if (!handle || !efi_hii_packagelist_exists(handle))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ free_packagelist(hii);
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+update_package_list(const struct efi_hii_database_protocol *this,
+ efi_hii_handle_t handle,
+ const struct efi_hii_package_list_header *package_list)
+{
+ struct efi_hii_packagelist *hii = handle;
+ struct efi_hii_package_header *package;
+ void *end;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p, %p", this, handle, package_list);
+
+ if (!handle || !efi_hii_packagelist_exists(handle))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (!package_list)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid,
+ get_unaligned_le32(&package_list->package_length));
+
+ package = ((void *)package_list) + sizeof(*package_list);
+ end = ((void *)package_list)
+ + get_unaligned_le32(&package_list->package_length);
+
+ while ((void *)package < end) {
+ EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
+ efi_hii_package_type(package),
+ efi_hii_package_len(package));
+
+ switch (efi_hii_package_type(package)) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ remove_guid_package(hii);
+ break;
+ case EFI_HII_PACKAGE_FORMS:
+ EFI_PRINT("Form package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ remove_strings_package(hii);
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ EFI_PRINT("Font package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ EFI_PRINT("Image package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ EFI_PRINT("Simple font package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ EFI_PRINT("Device path package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ remove_keyboard_package(hii);
+ break;
+ case EFI_HII_PACKAGE_ANIMATIONS:
+ EFI_PRINT("Animation package not supported\n");
+ ret = EFI_INVALID_PARAMETER;
+ break;
+ case EFI_HII_PACKAGE_END:
+ goto out;
+ case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
+ case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
+ default:
+ break;
+ }
+
+ /* TODO: already removed some packages */
+ if (ret != EFI_SUCCESS)
+ return EFI_EXIT(ret);
+
+ package = ((void *)package)
+ + efi_hii_package_len(package);
+ }
+out:
+ ret = add_packages(hii, package_list);
+
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+list_package_lists(const struct efi_hii_database_protocol *this,
+ u8 package_type,
+ const efi_guid_t *package_guid,
+ efi_uintn_t *handle_buffer_length,
+ efi_hii_handle_t *handle)
+{
+ struct efi_hii_packagelist *hii =
+ (struct efi_hii_packagelist *)handle;
+ int package_cnt, package_max;
+ efi_status_t ret = EFI_NOT_FOUND;
+
+ EFI_ENTRY("%p, %u, %pUl, %p, %p", this, package_type, package_guid,
+ handle_buffer_length, handle);
+
+ if (!handle_buffer_length ||
+ (*handle_buffer_length && !handle)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
+ (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ EFI_PRINT("package type=%x, guid=%pUl, length=%zu\n", (int)package_type,
+ package_guid, *handle_buffer_length);
+
+ package_cnt = 0;
+ package_max = *handle_buffer_length / sizeof(*handle);
+ list_for_each_entry(hii, &efi_package_lists, link) {
+ switch (package_type) {
+ case EFI_HII_PACKAGE_TYPE_ALL:
+ break;
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ if (!list_empty(&hii->guid_list))
+ break;
+ continue;
+ case EFI_HII_PACKAGE_STRINGS:
+ if (!list_empty(&hii->string_tables))
+ break;
+ continue;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ if (!list_empty(&hii->keyboard_packages))
+ break;
+ continue;
+ default:
+ continue;
+ }
+
+ package_cnt++;
+ if (package_cnt <= package_max) {
+ *handle++ = hii;
+ ret = EFI_SUCCESS;
+ } else {
+ ret = EFI_BUFFER_TOO_SMALL;
+ }
+ }
+ *handle_buffer_length = package_cnt * sizeof(*handle);
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+export_package_lists(const struct efi_hii_database_protocol *this,
+ efi_hii_handle_t handle,
+ efi_uintn_t *buffer_size,
+ struct efi_hii_package_list_header *buffer)
+{
+ EFI_ENTRY("%p, %p, %p, %p", this, handle, buffer_size, buffer);
+
+ if (!buffer_size || !buffer)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+register_package_notify(const struct efi_hii_database_protocol *this,
+ u8 package_type,
+ const efi_guid_t *package_guid,
+ const void *package_notify_fn,
+ efi_uintn_t notify_type,
+ efi_handle_t *notify_handle)
+{
+ EFI_ENTRY("%p, %u, %pUl, %p, %zu, %p", this, package_type,
+ package_guid, package_notify_fn, notify_type,
+ notify_handle);
+
+ if (!notify_handle)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
+ (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+unregister_package_notify(const struct efi_hii_database_protocol *this,
+ efi_handle_t notification_handle)
+{
+ EFI_ENTRY("%p, %p", this, notification_handle);
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+find_keyboard_layouts(const struct efi_hii_database_protocol *this,
+ u16 *key_guid_buffer_length,
+ efi_guid_t *key_guid_buffer)
+{
+ struct efi_keyboard_layout_data *layout_data;
+ int package_cnt, package_max;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer);
+
+ if (!key_guid_buffer_length ||
+ (*key_guid_buffer_length && !key_guid_buffer))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ package_cnt = 0;
+ package_max = *key_guid_buffer_length / sizeof(*key_guid_buffer);
+ list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
+ package_cnt++;
+ if (package_cnt <= package_max)
+ memcpy(key_guid_buffer++,
+ &layout_data->keyboard_layout.guid,
+ sizeof(*key_guid_buffer));
+ else
+ ret = EFI_BUFFER_TOO_SMALL;
+ }
+ *key_guid_buffer_length = package_cnt * sizeof(*key_guid_buffer);
+
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+get_keyboard_layout(const struct efi_hii_database_protocol *this,
+ efi_guid_t *key_guid,
+ u16 *keyboard_layout_length,
+ struct efi_hii_keyboard_layout *keyboard_layout)
+{
+ struct efi_keyboard_layout_data *layout_data;
+ u16 layout_length;
+
+ EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length,
+ keyboard_layout);
+
+ if (!keyboard_layout_length ||
+ (*keyboard_layout_length && !keyboard_layout))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* TODO: no notion of current keyboard layout */
+ if (!key_guid)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
+ if (!guidcmp(&layout_data->keyboard_layout.guid, key_guid))
+ goto found;
+ }
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+found:
+ layout_length =
+ get_unaligned_le16(&layout_data->keyboard_layout.layout_length);
+ if (*keyboard_layout_length < layout_length) {
+ *keyboard_layout_length = layout_length;
+ return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+ }
+
+ memcpy(keyboard_layout, &layout_data->keyboard_layout, layout_length);
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+set_keyboard_layout(const struct efi_hii_database_protocol *this,
+ efi_guid_t *key_guid)
+{
+ EFI_ENTRY("%p, %pUl", this, key_guid);
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+get_package_list_handle(const struct efi_hii_database_protocol *this,
+ efi_hii_handle_t package_list_handle,
+ efi_handle_t *driver_handle)
+{
+ struct efi_hii_packagelist *hii;
+
+ EFI_ENTRY("%p, %p, %p", this, package_list_handle, driver_handle);
+
+ if (!driver_handle)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ list_for_each_entry(hii, &efi_package_lists, link) {
+ if (hii == package_list_handle) {
+ *driver_handle = hii->driver_handle;
+ return EFI_EXIT(EFI_SUCCESS);
+ }
+ }
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+const struct efi_hii_database_protocol efi_hii_database = {
+ .new_package_list = new_package_list,
+ .remove_package_list = remove_package_list,
+ .update_package_list = update_package_list,
+ .list_package_lists = list_package_lists,
+ .export_package_lists = export_package_lists,
+ .register_package_notify = register_package_notify,
+ .unregister_package_notify = unregister_package_notify,
+ .find_keyboard_layouts = find_keyboard_layouts,
+ .get_keyboard_layout = get_keyboard_layout,
+ .set_keyboard_layout = set_keyboard_layout,
+ .get_package_list_handle = get_package_list_handle
+};
+
+/*
+ * EFI_HII_STRING_PROTOCOL
+ */
+
+static bool language_match(char *language, char *languages)
+{
+ size_t n;
+
+ n = strlen(language);
+ /* match primary language? */
+ if (!strncasecmp(language, languages, n) &&
+ (languages[n] == ';' || languages[n] == '\0'))
+ return true;
+
+ return false;
+}
+
+static efi_status_t EFIAPI
+new_string(const struct efi_hii_string_protocol *this,
+ efi_hii_handle_t package_list,
+ efi_string_id_t *string_id,
+ const u8 *language,
+ const u16 *language_name,
+ const efi_string_t string,
+ const struct efi_font_info *string_font_info)
+{
+ struct efi_hii_packagelist *hii = package_list;
+ struct efi_string_table *stbl;
+
+ EFI_ENTRY("%p, %p, %p, \"%s\", %p, \"%ls\", %p", this, package_list,
+ string_id, language, language_name, string,
+ string_font_info);
+
+ if (!package_list || !efi_hii_packagelist_exists(package_list))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (!string_id || !language || !string)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ if (language_match((char *)language, stbl->language)) {
+ efi_string_id_t new_id;
+ void *buf;
+ efi_string_t str;
+
+ new_id = ++hii->max_string_id;
+ if (stbl->nstrings < new_id) {
+ buf = realloc(stbl->strings,
+ sizeof(stbl->strings[0])
+ * new_id);
+ if (!buf)
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+ memset(&stbl->strings[stbl->nstrings], 0,
+ (new_id - stbl->nstrings)
+ * sizeof(stbl->strings[0]));
+ stbl->strings = buf;
+ stbl->nstrings = new_id;
+ }
+
+ str = u16_strdup(string);
+ if (!str)
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+ stbl->strings[new_id - 1].string = str;
+ *string_id = new_id;
+
+ return EFI_EXIT(EFI_SUCCESS);
+ }
+ }
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+get_string(const struct efi_hii_string_protocol *this,
+ const u8 *language,
+ efi_hii_handle_t package_list,
+ efi_string_id_t string_id,
+ efi_string_t string,
+ efi_uintn_t *string_size,
+ struct efi_font_info **string_font_info)
+{
+ struct efi_hii_packagelist *hii = package_list;
+ struct efi_string_table *stbl;
+
+ EFI_ENTRY("%p, \"%s\", %p, %u, %p, %p, %p", this, language,
+ package_list, string_id, string, string_size,
+ string_font_info);
+
+ if (!package_list || !efi_hii_packagelist_exists(package_list))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ if (language_match((char *)language, stbl->language)) {
+ efi_string_t str;
+ size_t len;
+
+ if (stbl->nstrings < string_id)
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ str = stbl->strings[string_id - 1].string;
+ if (str) {
+ len = (u16_strlen(str) + 1) * sizeof(u16);
+ if (*string_size < len) {
+ *string_size = len;
+
+ return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+ }
+ memcpy(string, str, len);
+ *string_size = len;
+ } else {
+ return EFI_EXIT(EFI_NOT_FOUND);
+ }
+
+ return EFI_EXIT(EFI_SUCCESS);
+ }
+ }
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+set_string(const struct efi_hii_string_protocol *this,
+ efi_hii_handle_t package_list,
+ efi_string_id_t string_id,
+ const u8 *language,
+ const efi_string_t string,
+ const struct efi_font_info *string_font_info)
+{
+ struct efi_hii_packagelist *hii = package_list;
+ struct efi_string_table *stbl;
+
+ EFI_ENTRY("%p, %p, %u, \"%s\", \"%ls\", %p", this, package_list,
+ string_id, language, string, string_font_info);
+
+ if (!package_list || !efi_hii_packagelist_exists(package_list))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (string_id > hii->max_string_id)
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (!string || !language)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ if (language_match((char *)language, stbl->language)) {
+ efi_string_t str;
+
+ if (hii->max_string_id < string_id)
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (stbl->nstrings < string_id) {
+ void *buf;
+
+ buf = realloc(stbl->strings,
+ string_id
+ * sizeof(stbl->strings[0]));
+ if (!buf)
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+ memset(&stbl->strings[string_id - 1], 0,
+ (string_id - stbl->nstrings)
+ * sizeof(stbl->strings[0]));
+ stbl->strings = buf;
+ }
+
+ str = u16_strdup(string);
+ if (!str)
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+ free(stbl->strings[string_id - 1].string);
+ stbl->strings[string_id - 1].string = str;
+
+ return EFI_EXIT(EFI_SUCCESS);
+ }
+ }
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+get_languages(const struct efi_hii_string_protocol *this,
+ efi_hii_handle_t package_list,
+ u8 *languages,
+ efi_uintn_t *languages_size)
+{
+ struct efi_hii_packagelist *hii = package_list;
+ struct efi_string_table *stbl;
+ size_t len = 0;
+ char *p;
+
+ EFI_ENTRY("%p, %p, %p, %p", this, package_list, languages,
+ languages_size);
+
+ if (!package_list || !efi_hii_packagelist_exists(package_list))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (!languages_size ||
+ (*languages_size && !languages))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* figure out required size: */
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ len += strlen((char *)stbl->language) + 1;
+ }
+
+ if (*languages_size < len) {
+ *languages_size = len;
+
+ return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+ }
+
+ p = (char *)languages;
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ if (p != (char *)languages)
+ *p++ = ';';
+ strcpy(p, stbl->language);
+ p += strlen((char *)stbl->language);
+ }
+ *p = '\0';
+
+ EFI_PRINT("languages: %s\n", languages);
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+get_secondary_languages(const struct efi_hii_string_protocol *this,
+ efi_hii_handle_t package_list,
+ const u8 *primary_language,
+ u8 *secondary_languages,
+ efi_uintn_t *secondary_languages_size)
+{
+ struct efi_hii_packagelist *hii = package_list;
+ struct efi_string_table *stbl;
+ bool found = false;
+
+ EFI_ENTRY("%p, %p, \"%s\", %p, %p", this, package_list,
+ primary_language, secondary_languages,
+ secondary_languages_size);
+
+ if (!package_list || !efi_hii_packagelist_exists(package_list))
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ if (!secondary_languages_size ||
+ (*secondary_languages_size && !secondary_languages))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ list_for_each_entry(stbl, &hii->string_tables, link) {
+ if (language_match((char *)primary_language, stbl->language)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return EFI_EXIT(EFI_INVALID_LANGUAGE);
+
+ /*
+ * TODO: What is secondary language?
+ * *secondary_languages = '\0';
+ * *secondary_languages_size = 0;
+ */
+
+ return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+const struct efi_hii_string_protocol efi_hii_string = {
+ .new_string = new_string,
+ .get_string = get_string,
+ .set_string = set_string,
+ .get_languages = get_languages,
+ .get_secondary_languages = get_secondary_languages
+};
diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c
new file mode 100644
index 00000000..26ea4b9b
--- /dev/null
+++ b/lib/efi_loader/efi_hii_config.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI Human Interface Infrastructure ... Configuration
+ *
+ * Copyright (c) 2017 Leif Lindholm
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+
+const efi_guid_t efi_guid_hii_config_routing_protocol
+ = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID;
+const efi_guid_t efi_guid_hii_config_access_protocol
+ = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
+
+/*
+ * EFI_HII_CONFIG_ROUTING_PROTOCOL
+ */
+
+static efi_status_t EFIAPI
+extract_config(const struct efi_hii_config_routing_protocol *this,
+ const efi_string_t request,
+ efi_string_t *progress,
+ efi_string_t *results)
+{
+ EFI_ENTRY("%p, \"%ls\", %p, %p", this, request, progress, results);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+export_config(const struct efi_hii_config_routing_protocol *this,
+ efi_string_t *results)
+{
+ EFI_ENTRY("%p, %p", this, results);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+route_config(const struct efi_hii_config_routing_protocol *this,
+ const efi_string_t configuration,
+ efi_string_t *progress)
+{
+ EFI_ENTRY("%p, \"%ls\", %p", this, configuration, progress);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+block_to_config(const struct efi_hii_config_routing_protocol *this,
+ const efi_string_t config_request,
+ const u8 *block,
+ const efi_uintn_t block_size,
+ efi_string_t *config,
+ efi_string_t *progress)
+{
+ EFI_ENTRY("%p, \"%ls\", %p, %zu, %p, %p", this, config_request,
+ block, block_size, config, progress);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+config_to_block(const struct efi_hii_config_routing_protocol *this,
+ const efi_string_t config_resp,
+ const u8 *block,
+ const efi_uintn_t *block_size,
+ efi_string_t *progress)
+{
+ EFI_ENTRY("%p, \"%ls\", %p, %p, %p", this, config_resp,
+ block, block_size, progress);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+static efi_status_t EFIAPI
+get_alt_config(const struct efi_hii_config_routing_protocol *this,
+ const efi_string_t config_resp,
+ const efi_guid_t *guid,
+ const efi_string_t name,
+ const struct efi_device_path *device_path,
+ const efi_string_t alt_cfg_id,
+ efi_string_t *alt_cfg_resp)
+{
+ EFI_ENTRY("%p, \"%ls\", %pUl, \"%ls\", %p, \"%ls\", %p",
+ this, config_resp, guid, name, device_path,
+ alt_cfg_id, alt_cfg_resp);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+}
+
+/*
+ * EFI_HII_ACCESS_PROTOCOL
+ */
+
+efi_status_t EFIAPI
+extract_config_access(const struct efi_hii_config_access_protocol *this,
+ const efi_string_t request,
+ efi_string_t *progress,
+ efi_string_t *results)
+{
+ EFI_ENTRY("%p, \"%ls\", %p, %p", this, request, progress, results);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+};
+
+efi_status_t EFIAPI
+route_config_access(const struct efi_hii_config_access_protocol *this,
+ const efi_string_t configuration,
+ efi_string_t *progress)
+{
+ EFI_ENTRY("%p, \"%ls\", %p", this, configuration, progress);
+
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+};
+
+efi_status_t EFIAPI
+form_callback(const struct efi_hii_config_access_protocol *this,
+ efi_browser_action_t action,
+ efi_question_id_t question_id,
+ u8 type,
+ union efi_ifr_type_value *value,
+ efi_browser_action_request_t *action_request)
+{
+ EFI_ENTRY("%p, 0x%zx, 0x%x, 0x%x, %p, %p", this, action,
+ question_id, type, value, action_request);
+
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+};
+
+const struct efi_hii_config_routing_protocol efi_hii_config_routing = {
+ .extract_config = extract_config,
+ .export_config = export_config,
+ .route_config = route_config,
+ .block_to_config = block_to_config,
+ .config_to_block = config_to_block,
+ .get_alt_config = get_alt_config
+};
+
+const struct efi_hii_config_access_protocol efi_hii_config_access = {
+ .extract_config_access = extract_config_access,
+ .route_config_access = route_config_access,
+ .form_callback = form_callback
+};
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
new file mode 100644
index 00000000..d5de6df1
--- /dev/null
+++ b/lib/efi_loader/efi_image_loader.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI image loader
+ *
+ * based partly on wine code
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <efi_loader.h>
+#include <pe.h>
+
+const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
+const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID;
+const efi_guid_t efi_guid_loaded_image = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+const efi_guid_t efi_guid_loaded_image_device_path =
+ EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID;
+const efi_guid_t efi_simple_file_system_protocol_guid =
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+
+static int machines[] = {
+#if defined(__aarch64__)
+ IMAGE_FILE_MACHINE_ARM64,
+#elif defined(__arm__)
+ IMAGE_FILE_MACHINE_ARM,
+ IMAGE_FILE_MACHINE_THUMB,
+ IMAGE_FILE_MACHINE_ARMNT,
+#endif
+
+#if defined(__x86_64__)
+ IMAGE_FILE_MACHINE_AMD64,
+#elif defined(__i386__)
+ IMAGE_FILE_MACHINE_I386,
+#endif
+
+#if defined(__riscv) && (__riscv_xlen == 32)
+ IMAGE_FILE_MACHINE_RISCV32,
+#endif
+
+#if defined(__riscv) && (__riscv_xlen == 64)
+ IMAGE_FILE_MACHINE_RISCV64,
+#endif
+ 0 };
+
+/**
+ * efi_print_image_info() - print information about a loaded image
+ *
+ * If the program counter is located within the image the offset to the base
+ * address is shown.
+ *
+ * @obj: EFI object
+ * @image: loaded image
+ * @pc: program counter (use NULL to suppress offset output)
+ * Return: status code
+ */
+static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
+ struct efi_loaded_image *image,
+ void *pc)
+{
+ printf("UEFI image");
+ printf(" [0x%p:0x%p]",
+ image->image_base, image->image_base + image->image_size - 1);
+ if (pc && pc >= image->image_base &&
+ pc < image->image_base + image->image_size)
+ printf(" pc=0x%zx", pc - image->image_base);
+ if (image->file_path)
+ printf(" '%pD'", image->file_path);
+ printf("\n");
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_print_image_infos() - print information about all loaded images
+ *
+ * @pc: program counter (use NULL to suppress offset output)
+ */
+void efi_print_image_infos(void *pc)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+
+ list_for_each_entry(efiobj, &efi_obj_list, link) {
+ list_for_each_entry(handler, &efiobj->protocols, link) {
+ if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
+ efi_print_image_info(
+ (struct efi_loaded_image_obj *)efiobj,
+ handler->protocol_interface, pc);
+ }
+ }
+ }
+}
+
+/**
+ * efi_loader_relocate() - relocate UEFI binary
+ *
+ * @rel: pointer to the relocation table
+ * @rel_size: size of the relocation table in bytes
+ * @efi_reloc: actual load address of the image
+ * @pref_address: preferred load address of the image
+ * Return: status code
+ */
+static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
+ unsigned long rel_size, void *efi_reloc,
+ unsigned long pref_address)
+{
+ unsigned long delta = (unsigned long)efi_reloc - pref_address;
+ const IMAGE_BASE_RELOCATION *end;
+ int i;
+
+ if (delta == 0)
+ return EFI_SUCCESS;
+
+ end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
+ while (rel < end && rel->SizeOfBlock) {
+ const uint16_t *relocs = (const uint16_t *)(rel + 1);
+ i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
+ while (i--) {
+ uint32_t offset = (uint32_t)(*relocs & 0xfff) +
+ rel->VirtualAddress;
+ int type = *relocs >> EFI_PAGE_SHIFT;
+ uint64_t *x64 = efi_reloc + offset;
+ uint32_t *x32 = efi_reloc + offset;
+ uint16_t *x16 = efi_reloc + offset;
+
+ switch (type) {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ case IMAGE_REL_BASED_HIGH:
+ *x16 += ((uint32_t)delta) >> 16;
+ break;
+ case IMAGE_REL_BASED_LOW:
+ *x16 += (uint16_t)delta;
+ break;
+ case IMAGE_REL_BASED_HIGHLOW:
+ *x32 += (uint32_t)delta;
+ break;
+ case IMAGE_REL_BASED_DIR64:
+ *x64 += (uint64_t)delta;
+ break;
+#ifdef __riscv
+ case IMAGE_REL_BASED_RISCV_HI20:
+ *x32 = ((*x32 & 0xfffff000) + (uint32_t)delta) |
+ (*x32 & 0x00000fff);
+ break;
+ case IMAGE_REL_BASED_RISCV_LOW12I:
+ case IMAGE_REL_BASED_RISCV_LOW12S:
+ /* We know that we're 4k aligned */
+ if (delta & 0xfff) {
+ printf("Unsupported reloc offset\n");
+ return EFI_LOAD_ERROR;
+ }
+ break;
+#endif
+ default:
+ printf("Unknown Relocation off %x type %x\n",
+ offset, type);
+ return EFI_LOAD_ERROR;
+ }
+ relocs++;
+ }
+ rel = (const IMAGE_BASE_RELOCATION *)relocs;
+ }
+ return EFI_SUCCESS;
+}
+
+void __weak invalidate_icache_all(void)
+{
+ /* If the system doesn't support icache_all flush, cross our fingers */
+}
+
+/**
+ * efi_set_code_and_data_type() - determine the memory types to be used for code
+ * and data.
+ *
+ * @loaded_image_info: image descriptor
+ * @image_type: field Subsystem of the optional header for
+ * Windows specific field
+ */
+static void efi_set_code_and_data_type(
+ struct efi_loaded_image *loaded_image_info,
+ uint16_t image_type)
+{
+ switch (image_type) {
+ case IMAGE_SUBSYSTEM_EFI_APPLICATION:
+ loaded_image_info->image_code_type = EFI_LOADER_CODE;
+ loaded_image_info->image_data_type = EFI_LOADER_DATA;
+ break;
+ case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+ loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE;
+ loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
+ break;
+ case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+ case IMAGE_SUBSYSTEM_EFI_ROM:
+ loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
+ loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
+ break;
+ default:
+ printf("%s: invalid image type: %u\n", __func__, image_type);
+ /* Let's assume it is an application */
+ loaded_image_info->image_code_type = EFI_LOADER_CODE;
+ loaded_image_info->image_data_type = EFI_LOADER_DATA;
+ break;
+ }
+}
+
+/**
+ * efi_load_pe() - relocate EFI binary
+ *
+ * This function loads all sections from a PE binary into a newly reserved
+ * piece of memory. On success the entry point is returned as handle->entry.
+ *
+ * @handle: loaded image handle
+ * @efi: pointer to the EFI binary
+ * @loaded_image_info: loaded image protocol
+ * Return: status code
+ */
+efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
+ struct efi_loaded_image *loaded_image_info)
+{
+ IMAGE_NT_HEADERS32 *nt;
+ IMAGE_DOS_HEADER *dos;
+ IMAGE_SECTION_HEADER *sections;
+ int num_sections;
+ void *efi_reloc;
+ int i;
+ const IMAGE_BASE_RELOCATION *rel;
+ unsigned long rel_size;
+ int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
+ uint64_t image_base;
+ unsigned long virt_size = 0;
+ int supported = 0;
+
+ dos = efi;
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
+ printf("%s: Invalid DOS Signature\n", __func__);
+ return EFI_LOAD_ERROR;
+ }
+
+ nt = (void *) ((char *)efi + dos->e_lfanew);
+ if (nt->Signature != IMAGE_NT_SIGNATURE) {
+ printf("%s: Invalid NT Signature\n", __func__);
+ return EFI_LOAD_ERROR;
+ }
+
+ for (i = 0; machines[i]; i++)
+ if (machines[i] == nt->FileHeader.Machine) {
+ supported = 1;
+ break;
+ }
+
+ if (!supported) {
+ printf("%s: Machine type 0x%04x is not supported\n",
+ __func__, nt->FileHeader.Machine);
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Calculate upper virtual address boundary */
+ num_sections = nt->FileHeader.NumberOfSections;
+ sections = (void *)&nt->OptionalHeader +
+ nt->FileHeader.SizeOfOptionalHeader;
+
+ for (i = num_sections - 1; i >= 0; i--) {
+ IMAGE_SECTION_HEADER *sec = &sections[i];
+ virt_size = max_t(unsigned long, virt_size,
+ sec->VirtualAddress + sec->Misc.VirtualSize);
+ }
+
+ /* Read 32/64bit specific header bits */
+ if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
+ IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
+ image_base = opt->ImageBase;
+ efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+ handle->image_type = opt->Subsystem;
+ efi_reloc = efi_alloc(virt_size,
+ loaded_image_info->image_code_type);
+ if (!efi_reloc) {
+ printf("%s: Could not allocate %lu bytes\n",
+ __func__, virt_size);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ handle->entry = efi_reloc + opt->AddressOfEntryPoint;
+ rel_size = opt->DataDirectory[rel_idx].Size;
+ rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+ virt_size = ALIGN(virt_size, opt->SectionAlignment);
+ } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
+ image_base = opt->ImageBase;
+ efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+ handle->image_type = opt->Subsystem;
+ efi_reloc = efi_alloc(virt_size,
+ loaded_image_info->image_code_type);
+ if (!efi_reloc) {
+ printf("%s: Could not allocate %lu bytes\n",
+ __func__, virt_size);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ handle->entry = efi_reloc + opt->AddressOfEntryPoint;
+ rel_size = opt->DataDirectory[rel_idx].Size;
+ rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+ virt_size = ALIGN(virt_size, opt->SectionAlignment);
+ } else {
+ printf("%s: Invalid optional header magic %x\n", __func__,
+ nt->OptionalHeader.Magic);
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Copy PE headers */
+ memcpy(efi_reloc, efi, sizeof(*dos) + sizeof(*nt)
+ + nt->FileHeader.SizeOfOptionalHeader
+ + num_sections * sizeof(IMAGE_SECTION_HEADER));
+
+ /* Load sections into RAM */
+ for (i = num_sections - 1; i >= 0; i--) {
+ IMAGE_SECTION_HEADER *sec = &sections[i];
+ memset(efi_reloc + sec->VirtualAddress, 0,
+ sec->Misc.VirtualSize);
+ memcpy(efi_reloc + sec->VirtualAddress,
+ efi + sec->PointerToRawData,
+ sec->SizeOfRawData);
+ }
+
+ /* Run through relocations */
+ if (efi_loader_relocate(rel, rel_size, efi_reloc,
+ (unsigned long)image_base) != EFI_SUCCESS) {
+ efi_free_pages((uintptr_t) efi_reloc,
+ (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Flush cache */
+ flush_cache((ulong)efi_reloc,
+ ALIGN(virt_size, EFI_CACHELINE_SIZE));
+ invalidate_icache_all();
+
+ /* Populate the loaded image interface bits */
+ loaded_image_info->image_base = efi_reloc;
+ loaded_image_info->image_size = virt_size;
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
new file mode 100644
index 00000000..89adf203
--- /dev/null
+++ b/lib/efi_loader/efi_memory.c
@@ -0,0 +1,788 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application memory management
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <init.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <watchdog.h>
+#include <linux/list_sort.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Magic number identifying memory allocated from pool */
+#define EFI_ALLOC_POOL_MAGIC 0x1fe67ddf6491caa2
+
+efi_uintn_t efi_memory_map_key;
+
+struct efi_mem_list {
+ struct list_head link;
+ struct efi_mem_desc desc;
+};
+
+#define EFI_CARVE_NO_OVERLAP -1
+#define EFI_CARVE_LOOP_AGAIN -2
+#define EFI_CARVE_OVERLAPS_NONRAM -3
+
+/* This list contains all memory map items */
+LIST_HEAD(efi_mem);
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+void *efi_bounce_buffer;
+#endif
+
+/**
+ * struct efi_pool_allocation - memory block allocated from pool
+ *
+ * @num_pages: number of pages allocated
+ * @checksum: checksum
+ * @data: allocated pool memory
+ *
+ * U-Boot services each UEFI AllocatePool() request as a separate
+ * (multiple) page allocation. We have to track the number of pages
+ * to be able to free the correct amount later.
+ *
+ * The checksum calculated in function checksum() is used in FreePool() to avoid
+ * freeing memory not allocated by AllocatePool() and duplicate freeing.
+ *
+ * EFI requires 8 byte alignment for pool allocations, so we can
+ * prepend each allocation with these header fields.
+ */
+struct efi_pool_allocation {
+ u64 num_pages;
+ u64 checksum;
+ char data[] __aligned(ARCH_DMA_MINALIGN);
+};
+
+/**
+ * checksum() - calculate checksum for memory allocated from pool
+ *
+ * @alloc: allocation header
+ * Return: checksum, always non-zero
+ */
+static u64 checksum(struct efi_pool_allocation *alloc)
+{
+ u64 addr = (uintptr_t)alloc;
+ u64 ret = (addr >> 32) ^ (addr << 32) ^ alloc->num_pages ^
+ EFI_ALLOC_POOL_MAGIC;
+ if (!ret)
+ ++ret;
+ return ret;
+}
+
+/*
+ * Sorts the memory list from highest address to lowest address
+ *
+ * When allocating memory we should always start from the highest
+ * address chunk, so sort the memory list such that the first list
+ * iterator gets the highest address and goes lower from there.
+ */
+static int efi_mem_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+ struct efi_mem_list *mema = list_entry(a, struct efi_mem_list, link);
+ struct efi_mem_list *memb = list_entry(b, struct efi_mem_list, link);
+
+ if (mema->desc.physical_start == memb->desc.physical_start)
+ return 0;
+ else if (mema->desc.physical_start < memb->desc.physical_start)
+ return 1;
+ else
+ return -1;
+}
+
+static uint64_t desc_get_end(struct efi_mem_desc *desc)
+{
+ return desc->physical_start + (desc->num_pages << EFI_PAGE_SHIFT);
+}
+
+static void efi_mem_sort(void)
+{
+ struct list_head *lhandle;
+ struct efi_mem_list *prevmem = NULL;
+ bool merge_again = true;
+
+ list_sort(NULL, &efi_mem, efi_mem_cmp);
+
+ /* Now merge entries that can be merged */
+ while (merge_again) {
+ merge_again = false;
+ list_for_each(lhandle, &efi_mem) {
+ struct efi_mem_list *lmem;
+ struct efi_mem_desc *prev = &prevmem->desc;
+ struct efi_mem_desc *cur;
+ uint64_t pages;
+
+ lmem = list_entry(lhandle, struct efi_mem_list, link);
+ if (!prevmem) {
+ prevmem = lmem;
+ continue;
+ }
+
+ cur = &lmem->desc;
+
+ if ((desc_get_end(cur) == prev->physical_start) &&
+ (prev->type == cur->type) &&
+ (prev->attribute == cur->attribute)) {
+ /* There is an existing map before, reuse it */
+ pages = cur->num_pages;
+ prev->num_pages += pages;
+ prev->physical_start -= pages << EFI_PAGE_SHIFT;
+ prev->virtual_start -= pages << EFI_PAGE_SHIFT;
+ list_del(&lmem->link);
+ free(lmem);
+
+ merge_again = true;
+ break;
+ }
+
+ prevmem = lmem;
+ }
+ }
+}
+
+/** efi_mem_carve_out - unmap memory region
+ *
+ * @map: memory map
+ * @carve_desc: memory region to unmap
+ * @overlap_only_ram: the carved out region may only overlap RAM
+ * Return Value: the number of overlapping pages which have been
+ * removed from the map,
+ * EFI_CARVE_NO_OVERLAP, if the regions don't overlap,
+ * EFI_CARVE_OVERLAPS_NONRAM, if the carve and map overlap,
+ * and the map contains anything but free ram
+ * (only when overlap_only_ram is true),
+ * EFI_CARVE_LOOP_AGAIN, if the mapping list should be
+ * traversed again, as it has been altered.
+ *
+ * Unmaps all memory occupied by the carve_desc region from the list entry
+ * pointed to by map.
+ *
+ * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
+ * to re-add the already carved out pages to the mapping.
+ */
+static s64 efi_mem_carve_out(struct efi_mem_list *map,
+ struct efi_mem_desc *carve_desc,
+ bool overlap_only_ram)
+{
+ struct efi_mem_list *newmap;
+ struct efi_mem_desc *map_desc = &map->desc;
+ uint64_t map_start = map_desc->physical_start;
+ uint64_t map_end = map_start + (map_desc->num_pages << EFI_PAGE_SHIFT);
+ uint64_t carve_start = carve_desc->physical_start;
+ uint64_t carve_end = carve_start +
+ (carve_desc->num_pages << EFI_PAGE_SHIFT);
+
+ /* check whether we're overlapping */
+ if ((carve_end <= map_start) || (carve_start >= map_end))
+ return EFI_CARVE_NO_OVERLAP;
+
+ /* We're overlapping with non-RAM, warn the caller if desired */
+ if (overlap_only_ram && (map_desc->type != EFI_CONVENTIONAL_MEMORY))
+ return EFI_CARVE_OVERLAPS_NONRAM;
+
+ /* Sanitize carve_start and carve_end to lie within our bounds */
+ carve_start = max(carve_start, map_start);
+ carve_end = min(carve_end, map_end);
+
+ /* Carving at the beginning of our map? Just move it! */
+ if (carve_start == map_start) {
+ if (map_end == carve_end) {
+ /* Full overlap, just remove map */
+ list_del(&map->link);
+ free(map);
+ } else {
+ map->desc.physical_start = carve_end;
+ map->desc.virtual_start = carve_end;
+ map->desc.num_pages = (map_end - carve_end)
+ >> EFI_PAGE_SHIFT;
+ }
+
+ return (carve_end - carve_start) >> EFI_PAGE_SHIFT;
+ }
+
+ /*
+ * Overlapping maps, just split the list map at carve_start,
+ * it will get moved or removed in the next iteration.
+ *
+ * [ map_desc |__carve_start__| newmap ]
+ */
+
+ /* Create a new map from [ carve_start ... map_end ] */
+ newmap = calloc(1, sizeof(*newmap));
+ newmap->desc = map->desc;
+ newmap->desc.physical_start = carve_start;
+ newmap->desc.virtual_start = carve_start;
+ newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
+ /* Insert before current entry (descending address order) */
+ list_add_tail(&newmap->link, &map->link);
+
+ /* Shrink the map to [ map_start ... carve_start ] */
+ map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
+
+ return EFI_CARVE_LOOP_AGAIN;
+}
+
+/**
+ * efi_add_memory_map() - add memory area to the memory map
+ *
+ * @start: start address, must be a multiple of EFI_PAGE_SIZE
+ * @pages: number of pages to add
+ * @memory_type: type of memory added
+ * @overlap_only_ram: the memory area must overlap existing
+ * Return: status code
+ */
+efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
+ bool overlap_only_ram)
+{
+ struct list_head *lhandle;
+ struct efi_mem_list *newlist;
+ bool carve_again;
+ uint64_t carved_pages = 0;
+ struct efi_event *evt;
+
+ EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__,
+ start, pages, memory_type, overlap_only_ram ? "yes" : "no");
+
+ if (memory_type >= EFI_MAX_MEMORY_TYPE)
+ return EFI_INVALID_PARAMETER;
+
+ if (!pages)
+ return EFI_SUCCESS;
+
+ ++efi_memory_map_key;
+ newlist = calloc(1, sizeof(*newlist));
+ newlist->desc.type = memory_type;
+ newlist->desc.physical_start = start;
+ newlist->desc.virtual_start = start;
+ newlist->desc.num_pages = pages;
+
+ switch (memory_type) {
+ case EFI_RUNTIME_SERVICES_CODE:
+ case EFI_RUNTIME_SERVICES_DATA:
+ newlist->desc.attribute = EFI_MEMORY_WB | EFI_MEMORY_RUNTIME;
+ break;
+ case EFI_MMAP_IO:
+ newlist->desc.attribute = EFI_MEMORY_RUNTIME;
+ break;
+ default:
+ newlist->desc.attribute = EFI_MEMORY_WB;
+ break;
+ }
+
+ /* Add our new map */
+ do {
+ carve_again = false;
+ list_for_each(lhandle, &efi_mem) {
+ struct efi_mem_list *lmem;
+ s64 r;
+
+ lmem = list_entry(lhandle, struct efi_mem_list, link);
+ r = efi_mem_carve_out(lmem, &newlist->desc,
+ overlap_only_ram);
+ switch (r) {
+ case EFI_CARVE_OVERLAPS_NONRAM:
+ /*
+ * The user requested to only have RAM overlaps,
+ * but we hit a non-RAM region. Error out.
+ */
+ return EFI_NO_MAPPING;
+ case EFI_CARVE_NO_OVERLAP:
+ /* Just ignore this list entry */
+ break;
+ case EFI_CARVE_LOOP_AGAIN:
+ /*
+ * We split an entry, but need to loop through
+ * the list again to actually carve it.
+ */
+ carve_again = true;
+ break;
+ default:
+ /* We carved a number of pages */
+ carved_pages += r;
+ carve_again = true;
+ break;
+ }
+
+ if (carve_again) {
+ /* The list changed, we need to start over */
+ break;
+ }
+ }
+ } while (carve_again);
+
+ if (overlap_only_ram && (carved_pages != pages)) {
+ /*
+ * The payload wanted to have RAM overlaps, but we overlapped
+ * with an unallocated region. Error out.
+ */
+ return EFI_NO_MAPPING;
+ }
+
+ /* Add our new map */
+ list_add_tail(&newlist->link, &efi_mem);
+
+ /* And make sure memory is listed in descending order */
+ efi_mem_sort();
+
+ /* Notify that the memory map was changed */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group &&
+ !guidcmp(evt->group,
+ &efi_guid_event_group_memory_map_change)) {
+ efi_signal_event(evt);
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_check_allocated() - validate address to be freed
+ *
+ * Check that the address is within allocated memory:
+ *
+ * * The address must be in a range of the memory map.
+ * * The address may not point to EFI_CONVENTIONAL_MEMORY.
+ *
+ * Page alignment is not checked as this is not a requirement of
+ * efi_free_pool().
+ *
+ * @addr: address of page to be freed
+ * @must_be_allocated: return success if the page is allocated
+ * Return: status code
+ */
+static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated)
+{
+ struct efi_mem_list *item;
+
+ list_for_each_entry(item, &efi_mem, link) {
+ u64 start = item->desc.physical_start;
+ u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT);
+
+ if (addr >= start && addr < end) {
+ if (must_be_allocated ^
+ (item->desc.type == EFI_CONVENTIONAL_MEMORY))
+ return EFI_SUCCESS;
+ else
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr)
+{
+ struct list_head *lhandle;
+
+ /*
+ * Prealign input max address, so we simplify our matching
+ * logic below and can just reuse it as return pointer.
+ */
+ max_addr &= ~EFI_PAGE_MASK;
+
+ list_for_each(lhandle, &efi_mem) {
+ struct efi_mem_list *lmem = list_entry(lhandle,
+ struct efi_mem_list, link);
+ struct efi_mem_desc *desc = &lmem->desc;
+ uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT;
+ uint64_t desc_end = desc->physical_start + desc_len;
+ uint64_t curmax = min(max_addr, desc_end);
+ uint64_t ret = curmax - len;
+
+ /* We only take memory from free RAM */
+ if (desc->type != EFI_CONVENTIONAL_MEMORY)
+ continue;
+
+ /* Out of bounds for max_addr */
+ if ((ret + len) > max_addr)
+ continue;
+
+ /* Out of bounds for upper map limit */
+ if ((ret + len) > desc_end)
+ continue;
+
+ /* Out of bounds for lower map limit */
+ if (ret < desc->physical_start)
+ continue;
+
+ /* Return the highest address in this map within bounds */
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate memory pages.
+ *
+ * @type type of allocation to be performed
+ * @memory_type usage type of the allocated memory
+ * @pages number of pages to be allocated
+ * @memory allocated memory
+ * @return status code
+ */
+efi_status_t efi_allocate_pages(int type, int memory_type,
+ efi_uintn_t pages, uint64_t *memory)
+{
+ u64 len = pages << EFI_PAGE_SHIFT;
+ efi_status_t ret;
+ uint64_t addr;
+
+ /* Check import parameters */
+ if (memory_type >= EFI_PERSISTENT_MEMORY_TYPE &&
+ memory_type <= 0x6FFFFFFF)
+ return EFI_INVALID_PARAMETER;
+ if (!memory)
+ return EFI_INVALID_PARAMETER;
+
+ switch (type) {
+ case EFI_ALLOCATE_ANY_PAGES:
+ /* Any page */
+ addr = efi_find_free_memory(len, -1ULL);
+ if (!addr)
+ return EFI_OUT_OF_RESOURCES;
+ break;
+ case EFI_ALLOCATE_MAX_ADDRESS:
+ /* Max address */
+ addr = efi_find_free_memory(len, *memory);
+ if (!addr)
+ return EFI_OUT_OF_RESOURCES;
+ break;
+ case EFI_ALLOCATE_ADDRESS:
+ /* Exact address, reserve it. The addr is already in *memory. */
+ ret = efi_check_allocated(*memory, false);
+ if (ret != EFI_SUCCESS)
+ return EFI_NOT_FOUND;
+ addr = *memory;
+ break;
+ default:
+ /* UEFI doesn't specify other allocation types */
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Reserve that map in our memory maps */
+ if (efi_add_memory_map(addr, pages, memory_type, true) != EFI_SUCCESS)
+ /* Map would overlap, bail out */
+ return EFI_OUT_OF_RESOURCES;
+
+ *memory = addr;
+
+ return EFI_SUCCESS;
+}
+
+void *efi_alloc(uint64_t len, int memory_type)
+{
+ uint64_t ret = 0;
+ uint64_t pages = efi_size_in_pages(len);
+ efi_status_t r;
+
+ r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages,
+ &ret);
+ if (r == EFI_SUCCESS)
+ return (void*)(uintptr_t)ret;
+
+ return NULL;
+}
+
+/**
+ * efi_free_pages() - free memory pages
+ *
+ * @memory: start of the memory area to be freed
+ * @pages: number of pages to be freed
+ * Return: status code
+ */
+efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
+{
+ efi_status_t ret;
+
+ ret = efi_check_allocated(memory, true);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ /* Sanity check */
+ if (!memory || (memory & EFI_PAGE_MASK) || !pages) {
+ printf("%s: illegal free 0x%llx, 0x%zx\n", __func__,
+ memory, pages);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ret = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+ /* Merging of adjacent free regions is missing */
+
+ if (ret != EFI_SUCCESS)
+ return EFI_NOT_FOUND;
+
+ return ret;
+}
+
+/**
+ * efi_allocate_pool - allocate memory from pool
+ *
+ * @pool_type: type of the pool from which memory is to be allocated
+ * @size: number of bytes to be allocated
+ * @buffer: allocated memory
+ * Return: status code
+ */
+efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
+{
+ efi_status_t r;
+ u64 addr;
+ struct efi_pool_allocation *alloc;
+ u64 num_pages = efi_size_in_pages(size +
+ sizeof(struct efi_pool_allocation));
+
+ if (!buffer)
+ return EFI_INVALID_PARAMETER;
+
+ if (size == 0) {
+ *buffer = NULL;
+ return EFI_SUCCESS;
+ }
+
+ r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages,
+ &addr);
+ if (r == EFI_SUCCESS) {
+ alloc = (struct efi_pool_allocation *)(uintptr_t)addr;
+ alloc->num_pages = num_pages;
+ alloc->checksum = checksum(alloc);
+ *buffer = alloc->data;
+ }
+
+ return r;
+}
+
+/**
+ * efi_free_pool() - free memory from pool
+ *
+ * @buffer: start of memory to be freed
+ * Return: status code
+ */
+efi_status_t efi_free_pool(void *buffer)
+{
+ efi_status_t ret;
+ struct efi_pool_allocation *alloc;
+
+ if (!buffer)
+ return EFI_INVALID_PARAMETER;
+
+ ret = efi_check_allocated((uintptr_t)buffer, true);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ alloc = container_of(buffer, struct efi_pool_allocation, data);
+
+ /* Check that this memory was allocated by efi_allocate_pool() */
+ if (((uintptr_t)alloc & EFI_PAGE_MASK) ||
+ alloc->checksum != checksum(alloc)) {
+ printf("%s: illegal free 0x%p\n", __func__, buffer);
+ return EFI_INVALID_PARAMETER;
+ }
+ /* Avoid double free */
+ alloc->checksum = 0;
+
+ ret = efi_free_pages((uintptr_t)alloc, alloc->num_pages);
+
+ return ret;
+}
+
+/*
+ * Get map describing memory usage.
+ *
+ * @memory_map_size on entry the size, in bytes, of the memory map buffer,
+ * on exit the size of the copied memory map
+ * @memory_map buffer to which the memory map is written
+ * @map_key key for the memory map
+ * @descriptor_size size of an individual memory descriptor
+ * @descriptor_version version number of the memory descriptor structure
+ * @return status code
+ */
+efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
+ struct efi_mem_desc *memory_map,
+ efi_uintn_t *map_key,
+ efi_uintn_t *descriptor_size,
+ uint32_t *descriptor_version)
+{
+ efi_uintn_t map_size = 0;
+ int map_entries = 0;
+ struct list_head *lhandle;
+ efi_uintn_t provided_map_size;
+
+ if (!memory_map_size)
+ return EFI_INVALID_PARAMETER;
+
+ provided_map_size = *memory_map_size;
+
+ list_for_each(lhandle, &efi_mem)
+ map_entries++;
+
+ map_size = map_entries * sizeof(struct efi_mem_desc);
+
+ *memory_map_size = map_size;
+
+ if (provided_map_size < map_size)
+ return EFI_BUFFER_TOO_SMALL;
+
+ if (!memory_map)
+ return EFI_INVALID_PARAMETER;
+
+ if (descriptor_size)
+ *descriptor_size = sizeof(struct efi_mem_desc);
+
+ if (descriptor_version)
+ *descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+
+ /* Copy list into array */
+ /* Return the list in ascending order */
+ memory_map = &memory_map[map_entries - 1];
+ list_for_each(lhandle, &efi_mem) {
+ struct efi_mem_list *lmem;
+
+ lmem = list_entry(lhandle, struct efi_mem_list, link);
+ *memory_map = lmem->desc;
+ memory_map--;
+ }
+
+ if (map_key)
+ *map_key = efi_memory_map_key;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_add_conventional_memory_map() - add a RAM memory area to the map
+ *
+ * @ram_start: start address of a RAM memory area
+ * @ram_end: end address of a RAM memory area
+ * @ram_top: max address to be used as conventional memory
+ * Return: status code
+ */
+efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end,
+ u64 ram_top)
+{
+ u64 pages;
+
+ /* Remove partial pages */
+ ram_end &= ~EFI_PAGE_MASK;
+ ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+
+ if (ram_end <= ram_start) {
+ /* Invalid mapping */
+ return EFI_INVALID_PARAMETER;
+ }
+
+ pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
+
+ efi_add_memory_map(ram_start, pages,
+ EFI_CONVENTIONAL_MEMORY, false);
+
+ /*
+ * Boards may indicate to the U-Boot memory core that they
+ * can not support memory above ram_top. Let's honor this
+ * in the efi_loader subsystem too by declaring any memory
+ * above ram_top as "already occupied by firmware".
+ */
+ if (ram_top < ram_start) {
+ /* ram_top is before this region, reserve all */
+ efi_add_memory_map(ram_start, pages,
+ EFI_BOOT_SERVICES_DATA, true);
+ } else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
+ /* ram_top is inside this region, reserve parts */
+ pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
+
+ efi_add_memory_map(ram_top, pages,
+ EFI_BOOT_SERVICES_DATA, true);
+ }
+
+ return EFI_SUCCESS;
+}
+
+__weak void efi_add_known_memory(void)
+{
+ u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK;
+ int i;
+
+ /*
+ * ram_top is just outside mapped memory. So use an offset of one for
+ * mapping the sandbox address.
+ */
+ ram_top = (uintptr_t)map_sysmem(ram_top - 1, 0) + 1;
+
+ /* Fix for 32bit targets with ram_top at 4G */
+ if (!ram_top)
+ ram_top = 0x100000000ULL;
+
+ /* Add RAM */
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ u64 ram_end, ram_start;
+
+ ram_start = (uintptr_t)map_sysmem(gd->bd->bi_dram[i].start, 0);
+ ram_end = ram_start + gd->bd->bi_dram[i].size;
+
+ efi_add_conventional_memory_map(ram_start, ram_end, ram_top);
+ }
+}
+
+/* Add memory regions for U-Boot's memory and for the runtime services code */
+static void add_u_boot_and_runtime(void)
+{
+ unsigned long runtime_start, runtime_end, runtime_pages;
+ unsigned long runtime_mask = EFI_PAGE_MASK;
+ unsigned long uboot_start, uboot_pages;
+ unsigned long uboot_stack_size = 16 * 1024 * 1024;
+
+ /* Add U-Boot */
+ uboot_start = ((uintptr_t)map_sysmem(gd->start_addr_sp, 0) -
+ uboot_stack_size) & ~EFI_PAGE_MASK;
+ uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
+ uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+ efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
+
+#if defined(__aarch64__)
+ /*
+ * Runtime Services must be 64KiB aligned according to the
+ * "AArch64 Platforms" section in the UEFI spec (2.7+).
+ */
+
+ runtime_mask = SZ_64K - 1;
+#endif
+
+ /*
+ * Add Runtime Services. We mark surrounding boottime code as runtime as
+ * well to fulfill the runtime alignment constraints but avoid padding.
+ */
+ runtime_start = (ulong)&__efi_runtime_start & ~runtime_mask;
+ runtime_end = (ulong)&__efi_runtime_stop;
+ runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
+ runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
+ efi_add_memory_map(runtime_start, runtime_pages,
+ EFI_RUNTIME_SERVICES_CODE, false);
+}
+
+int efi_memory_init(void)
+{
+ efi_add_known_memory();
+
+ add_u_boot_and_runtime();
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+ /* Request a 32bit 64MB bounce buffer region */
+ uint64_t efi_bounce_buffer_addr = 0xffffffff;
+
+ if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA,
+ (64 * 1024 * 1024) >> EFI_PAGE_SHIFT,
+ &efi_bounce_buffer_addr) != EFI_SUCCESS)
+ return -1;
+
+ efi_bounce_buffer = (void*)(uintptr_t)efi_bounce_buffer_addr;
+#endif
+
+ return 0;
+}
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
new file mode 100644
index 00000000..82d25958
--- /dev/null
+++ b/lib/efi_loader/efi_net.c
@@ -0,0 +1,946 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Simple network protocol
+ * PXE base code protocol
+ *
+ * Copyright (c) 2016 Alexander Graf
+ *
+ * The simple network protocol has the following statuses and services
+ * to move between them:
+ *
+ * Start(): EfiSimpleNetworkStopped -> EfiSimpleNetworkStarted
+ * Initialize(): EfiSimpleNetworkStarted -> EfiSimpleNetworkInitialized
+ * Shutdown(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted
+ * Stop(): EfiSimpleNetworkStarted -> EfiSimpleNetworkStopped
+ * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <malloc.h>
+
+static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
+static const efi_guid_t efi_pxe_base_code_protocol_guid =
+ EFI_PXE_BASE_CODE_PROTOCOL_GUID;
+static struct efi_pxe_packet *dhcp_ack;
+static bool new_rx_packet;
+static void *new_tx_packet;
+static void *transmit_buffer;
+
+/*
+ * The notification function of this event is called in every timer cycle
+ * to check if a new network packet has been received.
+ */
+static struct efi_event *network_timer_event;
+/*
+ * This event is signaled when a packet has been received.
+ */
+static struct efi_event *wait_for_packet;
+
+/**
+ * struct efi_net_obj - EFI object representing a network interface
+ *
+ * @header: EFI object header
+ * @net: simple network protocol interface
+ * @net_mode: status of the network interface
+ * @pxe: PXE base code protocol interface
+ * @pxe_mode: status of the PXE base code protocol
+ */
+struct efi_net_obj {
+ struct efi_object header;
+ struct efi_simple_network net;
+ struct efi_simple_network_mode net_mode;
+ struct efi_pxe_base_code_protocol pxe;
+ struct efi_pxe_mode pxe_mode;
+};
+
+/*
+ * efi_net_start() - start the network interface
+ *
+ * This function implements the Start service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p", this);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (this->mode->state != EFI_NETWORK_STOPPED) {
+ ret = EFI_ALREADY_STARTED;
+ } else {
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
+ this->mode->state = EFI_NETWORK_STARTED;
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * efi_net_stop() - stop the network interface
+ *
+ * This function implements the Stop service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p", this);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (this->mode->state == EFI_NETWORK_STOPPED) {
+ ret = EFI_NOT_STARTED;
+ } else {
+ /* Disable hardware and put it into the reset state */
+ eth_halt();
+ this->mode->state = EFI_NETWORK_STOPPED;
+ }
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * efi_net_initialize() - initialize the network interface
+ *
+ * This function implements the Initialize service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @extra_rx: extra receive buffer to be allocated
+ * @extra_tx: extra transmit buffer to be allocated
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
+ ulong extra_rx, ulong extra_tx)
+{
+ int ret;
+ efi_status_t r = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx);
+
+ /* Check parameters */
+ if (!this) {
+ r = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ case EFI_NETWORK_STARTED:
+ break;
+ default:
+ r = EFI_NOT_STARTED;
+ goto out;
+ }
+
+ /* Setup packet buffers */
+ net_init();
+ /* Disable hardware and put it into the reset state */
+ eth_halt();
+ /* Set current device according to environment variables */
+ eth_set_current();
+ /* Get hardware ready for send and receive operations */
+ ret = eth_init();
+ if (ret < 0) {
+ eth_halt();
+ this->mode->state = EFI_NETWORK_STOPPED;
+ r = EFI_DEVICE_ERROR;
+ goto out;
+ } else {
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
+ this->mode->state = EFI_NETWORK_INITIALIZED;
+ }
+out:
+ return EFI_EXIT(r);
+}
+
+/*
+ * efi_net_reset() - reinitialize the network interface
+ *
+ * This function implements the Reset service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @extended_verification: execute exhaustive verification
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
+ int extended_verification)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %x", this, extended_verification);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ break;
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ default:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
+ this->mode->state = EFI_NETWORK_STARTED;
+ ret = EFI_CALL(efi_net_initialize(this, 0, 0));
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * efi_net_shutdown() - shut down the network interface
+ *
+ * This function implements the Shutdown service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p", this);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ break;
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ default:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
+ eth_halt();
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
+ this->mode->state = EFI_NETWORK_STARTED;
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/*
+ * efi_net_receive_filters() - mange multicast receive filters
+ *
+ * This function implements the ReceiveFilters service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @enable: bit mask of receive filters to enable
+ * @disable: bit mask of receive filters to disable
+ * @reset_mcast_filter: true resets contents of the filters
+ * @mcast_filter_count: number of hardware MAC addresses in the new filters list
+ * @mcast_filter: list of new filters
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_receive_filters
+ (struct efi_simple_network *this, u32 enable, u32 disable,
+ int reset_mcast_filter, ulong mcast_filter_count,
+ struct efi_mac_address *mcast_filter)
+{
+ EFI_ENTRY("%p, %x, %x, %x, %lx, %p", this, enable, disable,
+ reset_mcast_filter, mcast_filter_count, mcast_filter);
+
+ return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/*
+ * efi_net_station_address() - set the hardware MAC address
+ *
+ * This function implements the StationAddress service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @reset: if true reset the address to default
+ * @new_mac: new MAC address
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_station_address
+ (struct efi_simple_network *this, int reset,
+ struct efi_mac_address *new_mac)
+{
+ EFI_ENTRY("%p, %x, %p", this, reset, new_mac);
+
+ return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/*
+ * efi_net_statistics() - reset or collect statistics of the network interface
+ *
+ * This function implements the Statistics service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @reset: if true, the statistics are reset
+ * @stat_size: size of the statistics table
+ * @stat_table: table to receive the statistics
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this,
+ int reset, ulong *stat_size,
+ void *stat_table)
+{
+ EFI_ENTRY("%p, %x, %p, %p", this, reset, stat_size, stat_table);
+
+ return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/*
+ * efi_net_mcastiptomac() - translate multicast IP address to MAC address
+ *
+ * This function implements the MCastIPtoMAC service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this: pointer to the protocol instance
+ * @ipv6: true if the IP address is an IPv6 address
+ * @ip: IP address
+ * @mac: MAC address
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this,
+ int ipv6,
+ struct efi_ip_address *ip,
+ struct efi_mac_address *mac)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac);
+
+ if (!this || !ip || !mac) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (ipv6) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ /* Multi-cast addresses are in the range 224.0.0.0 - 239.255.255.255 */
+ if ((ip->ip_addr[0] & 0xf0) != 0xe0) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ };
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ case EFI_NETWORK_STARTED:
+ break;
+ default:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ }
+
+ memset(mac, 0, sizeof(struct efi_mac_address));
+
+ /*
+ * Copy lower 23 bits of IPv4 multi-cast address
+ * RFC 1112, RFC 7042 2.1.1.
+ */
+ mac->mac_addr[0] = 0x01;
+ mac->mac_addr[1] = 0x00;
+ mac->mac_addr[2] = 0x5E;
+ mac->mac_addr[3] = ip->ip_addr[1] & 0x7F;
+ mac->mac_addr[4] = ip->ip_addr[2];
+ mac->mac_addr[5] = ip->ip_addr[3];
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_net_nvdata() - read or write NVRAM
+ *
+ * This function implements the GetStatus service of the Simple Network
+ * Protocol. See the UEFI spec for details.
+ *
+ * @this: the instance of the Simple Network Protocol
+ * @read_write: true for read, false for write
+ * @offset: offset in NVRAM
+ * @buffer_size: size of buffer
+ * @buffer: buffer
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_nvdata(struct efi_simple_network *this,
+ int read_write, ulong offset,
+ ulong buffer_size, char *buffer)
+{
+ EFI_ENTRY("%p, %x, %lx, %lx, %p", this, read_write, offset, buffer_size,
+ buffer);
+
+ return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/**
+ * efi_net_get_status() - get interrupt status
+ *
+ * This function implements the GetStatus service of the Simple Network
+ * Protocol. See the UEFI spec for details.
+ *
+ * @this: the instance of the Simple Network Protocol
+ * @int_status: interface status
+ * @txbuf: transmission buffer
+ */
+static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
+ u32 *int_status, void **txbuf)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p, %p", this, int_status, txbuf);
+
+ efi_timer_check();
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ case EFI_NETWORK_STARTED:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ default:
+ break;
+ }
+
+ if (int_status) {
+ *int_status = this->int_status;
+ this->int_status = 0;
+ }
+ if (txbuf)
+ *txbuf = new_tx_packet;
+
+ new_tx_packet = NULL;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_net_transmit() - transmit a packet
+ *
+ * This function implements the Transmit service of the Simple Network Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: the instance of the Simple Network Protocol
+ * @header_size: size of the media header
+ * @buffer_size: size of the buffer to receive the packet
+ * @buffer: buffer to receive the packet
+ * @src_addr: source hardware MAC address
+ * @dest_addr: destination hardware MAC address
+ * @protocol: type of header to build
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_transmit
+ (struct efi_simple_network *this, size_t header_size,
+ size_t buffer_size, void *buffer,
+ struct efi_mac_address *src_addr,
+ struct efi_mac_address *dest_addr, u16 *protocol)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this,
+ (unsigned long)header_size, (unsigned long)buffer_size,
+ buffer, src_addr, dest_addr, protocol);
+
+ efi_timer_check();
+
+ /* Check parameters */
+ if (!this || !buffer) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* We do not support jumbo packets */
+ if (buffer_size > PKTSIZE_ALIGN) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* At least the IP header has to fit into the buffer */
+ if (buffer_size < this->mode->media_header_size) {
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+
+ /*
+ * TODO:
+ * Support VLANs. Use net_set_ether() for copying the header. Use a
+ * U_BOOT_ENV_CALLBACK to update the media header size.
+ */
+ if (header_size) {
+ struct ethernet_hdr *header = buffer;
+
+ if (!dest_addr || !protocol ||
+ header_size != this->mode->media_header_size) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (!src_addr)
+ src_addr = &this->mode->current_address;
+
+ memcpy(header->et_dest, dest_addr, ARP_HLEN);
+ memcpy(header->et_src, src_addr, ARP_HLEN);
+ header->et_protlen = htons(*protocol);
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ case EFI_NETWORK_STARTED:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ default:
+ break;
+ }
+
+ /* Ethernet packets always fit, just bounce */
+ memcpy(transmit_buffer, buffer, buffer_size);
+ net_send_packet(transmit_buffer, buffer_size);
+
+ new_tx_packet = buffer;
+ this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_net_receive() - receive a packet from a network interface
+ *
+ * This function implements the Receive service of the Simple Network Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: the instance of the Simple Network Protocol
+ * @header_size: size of the media header
+ * @buffer_size: size of the buffer to receive the packet
+ * @buffer: buffer to receive the packet
+ * @src_addr: source MAC address
+ * @dest_addr: destination MAC address
+ * @protocol: protocol
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_net_receive
+ (struct efi_simple_network *this, size_t *header_size,
+ size_t *buffer_size, void *buffer,
+ struct efi_mac_address *src_addr,
+ struct efi_mac_address *dest_addr, u16 *protocol)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct ethernet_hdr *eth_hdr;
+ size_t hdr_size = sizeof(struct ethernet_hdr);
+ u16 protlen;
+
+ EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
+ buffer_size, buffer, src_addr, dest_addr, protocol);
+
+ /* Execute events */
+ efi_timer_check();
+
+ /* Check parameters */
+ if (!this || !buffer || !buffer_size) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ case EFI_NETWORK_STARTED:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ default:
+ break;
+ }
+
+ if (!new_rx_packet) {
+ ret = EFI_NOT_READY;
+ goto out;
+ }
+ /* Fill export parameters */
+ eth_hdr = (struct ethernet_hdr *)net_rx_packet;
+ protlen = ntohs(eth_hdr->et_protlen);
+ if (protlen == 0x8100) {
+ hdr_size += 4;
+ protlen = ntohs(*(u16 *)&net_rx_packet[hdr_size - 2]);
+ }
+ if (header_size)
+ *header_size = hdr_size;
+ if (dest_addr)
+ memcpy(dest_addr, eth_hdr->et_dest, ARP_HLEN);
+ if (src_addr)
+ memcpy(src_addr, eth_hdr->et_src, ARP_HLEN);
+ if (protocol)
+ *protocol = protlen;
+ if (*buffer_size < net_rx_packet_len) {
+ /* Packet doesn't fit, try again with bigger buffer */
+ *buffer_size = net_rx_packet_len;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+ /* Copy packet */
+ memcpy(buffer, net_rx_packet, net_rx_packet_len);
+ *buffer_size = net_rx_packet_len;
+ new_rx_packet = 0;
+ this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address
+ *
+ * This function is called by dhcp_handler().
+ *
+ * @pkt: packet received by dhcp_handler()
+ * @len: length of the packet received
+ */
+void efi_net_set_dhcp_ack(void *pkt, int len)
+{
+ int maxsize = sizeof(*dhcp_ack);
+
+ if (!dhcp_ack)
+ dhcp_ack = malloc(maxsize);
+
+ memcpy(dhcp_ack, pkt, min(len, maxsize));
+}
+
+/**
+ * efi_net_push() - callback for received network packet
+ *
+ * This function is called when a network packet is received by eth_rx().
+ *
+ * @pkt: network packet
+ * @len: length
+ */
+static void efi_net_push(void *pkt, int len)
+{
+ new_rx_packet = true;
+}
+
+/**
+ * efi_network_timer_notify() - check if a new network packet has been received
+ *
+ * This notification function is called in every timer cycle.
+ *
+ * @event: the event for which this notification function is registered
+ * @context: event context - not used in this function
+ */
+static void EFIAPI efi_network_timer_notify(struct efi_event *event,
+ void *context)
+{
+ struct efi_simple_network *this = (struct efi_simple_network *)context;
+
+ EFI_ENTRY("%p, %p", event, context);
+
+ /*
+ * Some network drivers do not support calling eth_rx() before
+ * initialization.
+ */
+ if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
+ goto out;
+
+ if (!new_rx_packet) {
+ push_packet = efi_net_push;
+ eth_rx();
+ push_packet = NULL;
+ if (new_rx_packet) {
+ /* Check that we at least received an Ethernet header */
+ if (net_rx_packet_len >=
+ sizeof(struct ethernet_hdr)) {
+ this->int_status |=
+ EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+ wait_for_packet->is_signaled = true;
+ } else {
+ new_rx_packet = 0;
+ }
+ }
+ }
+out:
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_start(
+ struct efi_pxe_base_code_protocol *this,
+ u8 use_ipv6)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_stop(
+ struct efi_pxe_base_code_protocol *this)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_dhcp(
+ struct efi_pxe_base_code_protocol *this,
+ u8 sort_offers)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_discover(
+ struct efi_pxe_base_code_protocol *this,
+ u16 type, u16 *layer, u8 bis,
+ struct efi_pxe_base_code_discover_info *info)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_mtftp(
+ struct efi_pxe_base_code_protocol *this,
+ u32 operation, void *buffer_ptr,
+ u8 overwrite, efi_uintn_t *buffer_size,
+ struct efi_ip_address server_ip, char *filename,
+ struct efi_pxe_base_code_mtftp_info *info,
+ u8 dont_use_buffer)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_udp_write(
+ struct efi_pxe_base_code_protocol *this,
+ u16 op_flags, struct efi_ip_address *dest_ip,
+ u16 *dest_port,
+ struct efi_ip_address *gateway_ip,
+ struct efi_ip_address *src_ip, u16 *src_port,
+ efi_uintn_t *header_size, void *header_ptr,
+ efi_uintn_t *buffer_size, void *buffer_ptr)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_udp_read(
+ struct efi_pxe_base_code_protocol *this,
+ u16 op_flags, struct efi_ip_address *dest_ip,
+ u16 *dest_port, struct efi_ip_address *src_ip,
+ u16 *src_port, efi_uintn_t *header_size,
+ void *header_ptr, efi_uintn_t *buffer_size,
+ void *buffer_ptr)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_set_ip_filter(
+ struct efi_pxe_base_code_protocol *this,
+ struct efi_pxe_base_code_filter *new_filter)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_arp(
+ struct efi_pxe_base_code_protocol *this,
+ struct efi_ip_address *ip_addr,
+ struct efi_mac_address *mac_addr)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_set_parameters(
+ struct efi_pxe_base_code_protocol *this,
+ u8 *new_auto_arp, u8 *new_send_guid,
+ u8 *new_ttl, u8 *new_tos,
+ u8 *new_make_callback)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_set_station_ip(
+ struct efi_pxe_base_code_protocol *this,
+ struct efi_ip_address *new_station_ip,
+ struct efi_ip_address *new_subnet_mask)
+{
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
+ struct efi_pxe_base_code_protocol *this,
+ u8 *new_dhcp_discover_valid,
+ u8 *new_dhcp_ack_received,
+ u8 *new_proxy_offer_received,
+ u8 *new_pxe_discover_valid,
+ u8 *new_pxe_reply_received,
+ u8 *new_pxe_bis_reply_received,
+ EFI_PXE_BASE_CODE_PACKET *new_dchp_discover,
+ EFI_PXE_BASE_CODE_PACKET *new_dhcp_acc,
+ EFI_PXE_BASE_CODE_PACKET *new_proxy_offer,
+ EFI_PXE_BASE_CODE_PACKET *new_pxe_discover,
+ EFI_PXE_BASE_CODE_PACKET *new_pxe_reply,
+ EFI_PXE_BASE_CODE_PACKET *new_pxe_bis_reply)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_net_register() - register the simple network protocol
+ *
+ * This gets called from do_bootefi_exec().
+ */
+efi_status_t efi_net_register(void)
+{
+ struct efi_net_obj *netobj = NULL;
+ efi_status_t r;
+
+ if (!eth_get_dev()) {
+ /* No network device active, don't expose any */
+ return EFI_SUCCESS;
+ }
+
+ /* We only expose the "active" network device, so one is enough */
+ netobj = calloc(1, sizeof(*netobj));
+ if (!netobj)
+ goto out_of_resources;
+
+ /* Allocate an aligned transmit buffer */
+ transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
+ if (!transmit_buffer)
+ goto out_of_resources;
+ transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
+
+ /* Hook net up to the device list */
+ efi_add_handle(&netobj->header);
+
+ /* Fill in object data */
+ r = efi_add_protocol(&netobj->header, &efi_net_guid,
+ &netobj->net);
+ if (r != EFI_SUCCESS)
+ goto failure_to_add_protocol;
+ r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
+ efi_dp_from_eth());
+ if (r != EFI_SUCCESS)
+ goto failure_to_add_protocol;
+ r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
+ &netobj->pxe);
+ if (r != EFI_SUCCESS)
+ goto failure_to_add_protocol;
+ netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
+ netobj->net.start = efi_net_start;
+ netobj->net.stop = efi_net_stop;
+ netobj->net.initialize = efi_net_initialize;
+ netobj->net.reset = efi_net_reset;
+ netobj->net.shutdown = efi_net_shutdown;
+ netobj->net.receive_filters = efi_net_receive_filters;
+ netobj->net.station_address = efi_net_station_address;
+ netobj->net.statistics = efi_net_statistics;
+ netobj->net.mcastiptomac = efi_net_mcastiptomac;
+ netobj->net.nvdata = efi_net_nvdata;
+ netobj->net.get_status = efi_net_get_status;
+ netobj->net.transmit = efi_net_transmit;
+ netobj->net.receive = efi_net_receive;
+ netobj->net.mode = &netobj->net_mode;
+ netobj->net_mode.state = EFI_NETWORK_STOPPED;
+ memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
+ netobj->net_mode.hwaddr_size = ARP_HLEN;
+ netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
+ netobj->net_mode.max_packet_size = PKTSIZE;
+ netobj->net_mode.if_type = ARP_ETHER;
+
+ netobj->pxe.revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
+ netobj->pxe.start = efi_pxe_base_code_start;
+ netobj->pxe.stop = efi_pxe_base_code_stop;
+ netobj->pxe.dhcp = efi_pxe_base_code_dhcp;
+ netobj->pxe.discover = efi_pxe_base_code_discover;
+ netobj->pxe.mtftp = efi_pxe_base_code_mtftp;
+ netobj->pxe.udp_write = efi_pxe_base_code_udp_write;
+ netobj->pxe.udp_read = efi_pxe_base_code_udp_read;
+ netobj->pxe.set_ip_filter = efi_pxe_base_code_set_ip_filter;
+ netobj->pxe.arp = efi_pxe_base_code_arp;
+ netobj->pxe.set_parameters = efi_pxe_base_code_set_parameters;
+ netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip;
+ netobj->pxe.set_packets = efi_pxe_base_code_set_packets;
+ netobj->pxe.mode = &netobj->pxe_mode;
+ if (dhcp_ack)
+ netobj->pxe_mode.dhcp_ack = *dhcp_ack;
+
+ /*
+ * Create WaitForPacket event.
+ */
+ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
+ efi_network_timer_notify, NULL, NULL,
+ &wait_for_packet);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to register network event\n");
+ return r;
+ }
+ netobj->net.wait_for_packet = wait_for_packet;
+ /*
+ * Create a timer event.
+ *
+ * The notification function is used to check if a new network packet
+ * has been received.
+ *
+ * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
+ */
+ r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+ efi_network_timer_notify, &netobj->net, NULL,
+ &network_timer_event);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to register network event\n");
+ return r;
+ }
+ /* Network is time critical, create event in every timer cycle */
+ r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to set network timer\n");
+ return r;
+ }
+
+ return EFI_SUCCESS;
+failure_to_add_protocol:
+ printf("ERROR: Failure to add protocol\n");
+ return r;
+out_of_resources:
+ free(netobj);
+ /* free(transmit_buffer) not needed yet */
+ printf("ERROR: Out of memory\n");
+ return EFI_OUT_OF_RESOURCES;
+}
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
new file mode 100644
index 00000000..f68b0fdc
--- /dev/null
+++ b/lib/efi_loader/efi_root_node.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Root node for system services
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <efi_loader.h>
+
+const efi_guid_t efi_u_boot_guid = U_BOOT_GUID;
+
+efi_handle_t efi_root = NULL;
+
+struct efi_root_dp {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path end;
+} __packed;
+
+/**
+ * efi_root_node_register() - create root node
+ *
+ * Create the root node on which we install all protocols that are
+ * not related to a loaded image or a driver.
+ *
+ * Return: status code
+ */
+efi_status_t efi_root_node_register(void)
+{
+ efi_status_t ret;
+ struct efi_root_dp *dp;
+
+ /* Create device path protocol */
+ dp = calloc(1, sizeof(*dp));
+ if (!dp)
+ return EFI_OUT_OF_RESOURCES;
+
+ /* Fill vendor node */
+ dp->vendor.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ dp->vendor.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+ dp->vendor.dp.length = sizeof(struct efi_device_path_vendor);
+ dp->vendor.guid = efi_u_boot_guid;
+
+ /* Fill end node */
+ dp->end.type = DEVICE_PATH_TYPE_END;
+ dp->end.sub_type = DEVICE_PATH_SUB_TYPE_END;
+ dp->end.length = sizeof(struct efi_device_path);
+
+ /* Create root node and install protocols */
+ ret = EFI_CALL(efi_install_multiple_protocol_interfaces
+ (&efi_root,
+ /* Device path protocol */
+ &efi_guid_device_path, dp,
+#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT)
+ /* Device path to text protocol */
+ &efi_guid_device_path_to_text_protocol,
+ (void *)&efi_device_path_to_text,
+#endif
+ /* Device path utilities protocol */
+ &efi_guid_device_path_utilities_protocol,
+ (void *)&efi_device_path_utilities,
+#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL2)
+#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
+ /* Deprecated Unicode collation protocol */
+ &efi_guid_unicode_collation_protocol,
+ (void *)&efi_unicode_collation_protocol,
+#endif
+ /* Current Unicode collation protocol */
+ &efi_guid_unicode_collation_protocol2,
+ (void *)&efi_unicode_collation_protocol2,
+#endif
+#if CONFIG_IS_ENABLED(EFI_LOADER_HII)
+ /* HII string protocol */
+ &efi_guid_hii_string_protocol,
+ (void *)&efi_hii_string,
+ /* HII database protocol */
+ &efi_guid_hii_database_protocol,
+ (void *)&efi_hii_database,
+ /* HII configuration routing protocol */
+ &efi_guid_hii_config_routing_protocol,
+ (void *)&efi_hii_config_routing,
+#endif
+ NULL));
+ efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE;
+ return ret;
+}
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
new file mode 100644
index 00000000..df0485cd
--- /dev/null
+++ b/lib/efi_loader/efi_runtime.c
@@ -0,0 +1,883 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application runtime services
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <elf.h>
+#include <efi_loader.h>
+#include <rtc.h>
+#include <u-boot/crc.h>
+
+/* For manual relocation support */
+DECLARE_GLOBAL_DATA_PTR;
+
+struct efi_runtime_mmio_list {
+ struct list_head link;
+ void **ptr;
+ u64 paddr;
+ u64 len;
+};
+
+/* This list contains all runtime available mmio regions */
+LIST_HEAD(efi_runtime_mmio);
+
+static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
+
+/*
+ * TODO(sjg@chromium.org): These defines and structures should come from the ELF
+ * header for each architecture (or a generic header) rather than being repeated
+ * here.
+ */
+#if defined(__aarch64__)
+#define R_RELATIVE R_AARCH64_RELATIVE
+#define R_MASK 0xffffffffULL
+#define IS_RELA 1
+#elif defined(__arm__)
+#define R_RELATIVE R_ARM_RELATIVE
+#define R_MASK 0xffULL
+#elif defined(__i386__)
+#define R_RELATIVE R_386_RELATIVE
+#define R_MASK 0xffULL
+#elif defined(__x86_64__)
+#define R_RELATIVE R_X86_64_RELATIVE
+#define R_MASK 0xffffffffULL
+#define IS_RELA 1
+#elif defined(__riscv)
+#define R_RELATIVE R_RISCV_RELATIVE
+#define R_MASK 0xffULL
+#define IS_RELA 1
+
+struct dyn_sym {
+ ulong foo1;
+ ulong addr;
+ u32 foo2;
+ u32 foo3;
+};
+#if (__riscv_xlen == 32)
+#define R_ABSOLUTE R_RISCV_32
+#define SYM_INDEX 8
+#elif (__riscv_xlen == 64)
+#define R_ABSOLUTE R_RISCV_64
+#define SYM_INDEX 32
+#else
+#error unknown riscv target
+#endif
+#else
+#error Need to add relocation awareness
+#endif
+
+struct elf_rel {
+ ulong *offset;
+ ulong info;
+};
+
+struct elf_rela {
+ ulong *offset;
+ ulong info;
+ long addend;
+};
+
+static __efi_runtime_data struct efi_mem_desc *efi_virtmap;
+static __efi_runtime_data efi_uintn_t efi_descriptor_count;
+static __efi_runtime_data efi_uintn_t efi_descriptor_size;
+
+/*
+ * EFI runtime code lives in two stages. In the first stage, U-Boot and an EFI
+ * payload are running concurrently at the same time. In this mode, we can
+ * handle a good number of runtime callbacks
+ */
+
+efi_status_t efi_init_runtime_supported(void)
+{
+ u16 efi_runtime_services_supported =
+ EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP |
+ EFI_RT_SUPPORTED_CONVERT_POINTER;
+
+ /*
+ * This value must be synced with efi_runtime_detach_list
+ * as well as efi_runtime_services.
+ */
+#ifdef CONFIG_EFI_HAVE_RUNTIME_RESET
+ efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
+#endif
+
+ return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(efi_runtime_services_supported),
+ &efi_runtime_services_supported));
+}
+
+/**
+ * efi_update_table_header_crc32() - Update crc32 in table header
+ *
+ * @table: EFI table
+ */
+void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table)
+{
+ table->crc32 = 0;
+ table->crc32 = crc32(0, (const unsigned char *)table,
+ table->headersize);
+}
+
+/**
+ * efi_reset_system_boottime() - reset system at boot time
+ *
+ * This function implements the ResetSystem() runtime service before
+ * SetVirtualAddressMap() is called.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @reset_type: type of reset to perform
+ * @reset_status: status code for the reset
+ * @data_size: size of reset_data
+ * @reset_data: information about the reset
+ */
+static void EFIAPI efi_reset_system_boottime(
+ enum efi_reset_type reset_type,
+ efi_status_t reset_status,
+ unsigned long data_size, void *reset_data)
+{
+ struct efi_event *evt;
+
+ EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
+ reset_data);
+
+ /* Notify reset */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group &&
+ !guidcmp(evt->group,
+ &efi_guid_event_group_reset_system)) {
+ efi_signal_event(evt);
+ break;
+ }
+ }
+ switch (reset_type) {
+ case EFI_RESET_COLD:
+ case EFI_RESET_WARM:
+ case EFI_RESET_PLATFORM_SPECIFIC:
+ do_reset(NULL, 0, 0, NULL);
+ break;
+ case EFI_RESET_SHUTDOWN:
+#ifdef CONFIG_CMD_POWEROFF
+ do_poweroff(NULL, 0, 0, NULL);
+#endif
+ break;
+ }
+
+ while (1) { }
+}
+
+/**
+ * efi_get_time_boottime() - get current time at boot time
+ *
+ * This function implements the GetTime runtime service before
+ * SetVirtualAddressMap() is called.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time: pointer to structure to receive current time
+ * @capabilities: pointer to structure to receive RTC properties
+ * Returns: status code
+ */
+static efi_status_t EFIAPI efi_get_time_boottime(
+ struct efi_time *time,
+ struct efi_time_cap *capabilities)
+{
+#ifdef CONFIG_EFI_GET_TIME
+ efi_status_t ret = EFI_SUCCESS;
+ struct rtc_time tm;
+ struct udevice *dev;
+
+ EFI_ENTRY("%p %p", time, capabilities);
+
+ if (!time) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (uclass_get_device(UCLASS_RTC, 0, &dev) ||
+ dm_rtc_get(dev, &tm)) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ if (dm_rtc_get(dev, &tm)) {
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
+ memset(time, 0, sizeof(*time));
+ time->year = tm.tm_year;
+ time->month = tm.tm_mon;
+ time->day = tm.tm_mday;
+ time->hour = tm.tm_hour;
+ time->minute = tm.tm_min;
+ time->second = tm.tm_sec;
+ if (tm.tm_isdst)
+ time->daylight =
+ EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT;
+ time->timezone = EFI_UNSPECIFIED_TIMEZONE;
+
+ if (capabilities) {
+ /* Set reasonable dummy values */
+ capabilities->resolution = 1; /* 1 Hz */
+ capabilities->accuracy = 100000000; /* 100 ppm */
+ capabilities->sets_to_zero = false;
+ }
+out:
+ return EFI_EXIT(ret);
+#else
+ EFI_ENTRY("%p %p", time, capabilities);
+ return EFI_EXIT(EFI_UNSUPPORTED);
+#endif
+}
+
+#ifdef CONFIG_EFI_SET_TIME
+
+/**
+ * efi_validate_time() - checks if timestamp is valid
+ *
+ * @time: timestamp to validate
+ * Returns: 0 if timestamp is valid, 1 otherwise
+ */
+static int efi_validate_time(struct efi_time *time)
+{
+ return (!time ||
+ time->year < 1900 || time->year > 9999 ||
+ !time->month || time->month > 12 || !time->day ||
+ time->day > rtc_month_days(time->month - 1, time->year) ||
+ time->hour > 23 || time->minute > 59 || time->second > 59 ||
+ time->nanosecond > 999999999 ||
+ time->daylight &
+ ~(EFI_TIME_IN_DAYLIGHT | EFI_TIME_ADJUST_DAYLIGHT) ||
+ ((time->timezone < -1440 || time->timezone > 1440) &&
+ time->timezone != EFI_UNSPECIFIED_TIMEZONE));
+}
+
+#endif
+
+/**
+ * efi_set_time_boottime() - set current time
+ *
+ * This function implements the SetTime() runtime service before
+ * SetVirtualAddressMap() is called.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time: pointer to structure to with current time
+ * Returns: status code
+ */
+static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
+{
+#ifdef CONFIG_EFI_SET_TIME
+ efi_status_t ret = EFI_SUCCESS;
+ struct rtc_time tm;
+ struct udevice *dev;
+
+ EFI_ENTRY("%p", time);
+
+ if (efi_validate_time(time)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (uclass_get_device(UCLASS_RTC, 0, &dev)) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = time->year;
+ tm.tm_mon = time->month;
+ tm.tm_mday = time->day;
+ tm.tm_hour = time->hour;
+ tm.tm_min = time->minute;
+ tm.tm_sec = time->second;
+ tm.tm_isdst = time->daylight ==
+ (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
+ /* Calculate day of week */
+ rtc_calc_weekday(&tm);
+
+ if (dm_rtc_set(dev, &tm))
+ ret = EFI_DEVICE_ERROR;
+out:
+ return EFI_EXIT(ret);
+#else
+ EFI_ENTRY("%p", time);
+ return EFI_EXIT(EFI_UNSUPPORTED);
+#endif
+}
+/**
+ * efi_reset_system() - reset system
+ *
+ * This function implements the ResetSystem() runtime service after
+ * SetVirtualAddressMap() is called. It only executes an endless loop.
+ * Boards may override the helpers below to implement reset functionality.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @reset_type: type of reset to perform
+ * @reset_status: status code for the reset
+ * @data_size: size of reset_data
+ * @reset_data: information about the reset
+ */
+void __weak __efi_runtime EFIAPI efi_reset_system(
+ enum efi_reset_type reset_type,
+ efi_status_t reset_status,
+ unsigned long data_size, void *reset_data)
+{
+ /* Nothing we can do */
+ while (1) { }
+}
+
+/**
+ * efi_reset_system_init() - initialize the reset driver
+ *
+ * Boards may override this function to initialize the reset driver.
+ */
+efi_status_t __weak efi_reset_system_init(void)
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_get_time() - get current time
+ *
+ * This function implements the GetTime runtime service after
+ * SetVirtualAddressMap() is called. As the U-Boot driver are not available
+ * anymore only an error code is returned.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time: pointer to structure to receive current time
+ * @capabilities: pointer to structure to receive RTC properties
+ * Returns: status code
+ */
+efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
+ struct efi_time *time,
+ struct efi_time_cap *capabilities)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_set_time() - set current time
+ *
+ * This function implements the SetTime runtime service after
+ * SetVirtualAddressMap() is called. As the U-Boot driver are not available
+ * anymore only an error code is returned.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time: pointer to structure to with current time
+ * Returns: status code
+ */
+efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_is_runtime_service_pointer() - check if pointer points to runtime table
+ *
+ * @p: pointer to check
+ * Return: true if the pointer points to a service function pointer in the
+ * runtime table
+ */
+static bool efi_is_runtime_service_pointer(void *p)
+{
+ return (p >= (void *)&efi_runtime_services.get_time &&
+ p <= (void *)&efi_runtime_services.query_variable_info) ||
+ p == (void *)&efi_events.prev ||
+ p == (void *)&efi_events.next;
+}
+
+/**
+ * efi_runtime_detach() - detach unimplemented runtime functions
+ */
+void efi_runtime_detach(void)
+{
+ efi_runtime_services.reset_system = efi_reset_system;
+ efi_runtime_services.get_time = efi_get_time;
+ efi_runtime_services.set_time = efi_set_time;
+
+ /* Update CRC32 */
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
+}
+
+/**
+ * efi_set_virtual_address_map_runtime() - change from physical to virtual
+ * mapping
+ *
+ * This function implements the SetVirtualAddressMap() runtime service after
+ * it is first called.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @memory_map_size: size of the virtual map
+ * @descriptor_size: size of an entry in the map
+ * @descriptor_version: version of the map entries
+ * @virtmap: virtual address mapping information
+ * Return: status code EFI_UNSUPPORTED
+ */
+static __efi_runtime efi_status_t EFIAPI efi_set_virtual_address_map_runtime(
+ efi_uintn_t memory_map_size,
+ efi_uintn_t descriptor_size,
+ uint32_t descriptor_version,
+ struct efi_mem_desc *virtmap)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_convert_pointer_runtime() - convert from physical to virtual pointer
+ *
+ * This function implements the ConvertPointer() runtime service after
+ * the first call to SetVirtualAddressMap().
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @debug_disposition: indicates if pointer may be converted to NULL
+ * @address: pointer to be converted
+ * Return: status code EFI_UNSUPPORTED
+ */
+static __efi_runtime efi_status_t EFIAPI efi_convert_pointer_runtime(
+ efi_uintn_t debug_disposition, void **address)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_convert_pointer_runtime() - convert from physical to virtual pointer
+ *
+ * This function implements the ConvertPointer() runtime service until
+ * the first call to SetVirtualAddressMap().
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @debug_disposition: indicates if pointer may be converted to NULL
+ * @address: pointer to be converted
+ * Return: status code EFI_UNSUPPORTED
+ */
+static __efi_runtime efi_status_t EFIAPI efi_convert_pointer(
+ efi_uintn_t debug_disposition, void **address)
+{
+ efi_physical_addr_t addr = (uintptr_t)*address;
+ efi_uintn_t i;
+ efi_status_t ret = EFI_NOT_FOUND;
+
+ EFI_ENTRY("%zu %p", debug_disposition, address);
+
+ if (!efi_virtmap) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+
+ if (!address) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ for (i = 0; i < efi_descriptor_count; i++) {
+ struct efi_mem_desc *map = (void *)efi_virtmap +
+ (efi_descriptor_size * i);
+
+ if (addr >= map->physical_start &&
+ (addr < map->physical_start
+ + (map->num_pages << EFI_PAGE_SHIFT))) {
+ *address = (void *)(uintptr_t)
+ (addr + map->virtual_start -
+ map->physical_start);
+
+ ret = EFI_SUCCESS;
+ break;
+ }
+ }
+
+out:
+ return EFI_EXIT(ret);
+}
+
+static __efi_runtime void efi_relocate_runtime_table(ulong offset)
+{
+ ulong patchoff;
+ void **pos;
+
+ /* Relocate the runtime services pointers */
+ patchoff = offset - gd->relocaddr;
+ for (pos = (void **)&efi_runtime_services.get_time;
+ pos <= (void **)&efi_runtime_services.query_variable_info; ++pos) {
+ if (*pos)
+ *pos += patchoff;
+ }
+
+ /*
+ * The entry for SetVirtualAddress() must point to a physical address.
+ * After the first execution the service must return EFI_UNSUPPORTED.
+ */
+ efi_runtime_services.set_virtual_address_map =
+ &efi_set_virtual_address_map_runtime;
+
+ /*
+ * The entry for ConvertPointer() must point to a physical address.
+ * The service is not usable after SetVirtualAddress().
+ */
+ efi_runtime_services.convert_pointer = &efi_convert_pointer_runtime;
+
+ /*
+ * TODO: Update UEFI variable RuntimeServicesSupported removing flags
+ * EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP and
+ * EFI_RT_SUPPORTED_CONVERT_POINTER as required by the UEFI spec 2.8.
+ */
+
+ /* Update CRC32 */
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
+}
+
+/* Relocate EFI runtime to uboot_reloc_base = offset */
+void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
+{
+#ifdef IS_RELA
+ struct elf_rela *rel = (void*)&__efi_runtime_rel_start;
+#else
+ struct elf_rel *rel = (void*)&__efi_runtime_rel_start;
+ static ulong lastoff = CONFIG_SYS_TEXT_BASE;
+#endif
+
+ debug("%s: Relocating to offset=%lx\n", __func__, offset);
+ for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) {
+ ulong base = CONFIG_SYS_TEXT_BASE;
+ ulong *p;
+ ulong newaddr;
+
+ p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
+
+ /*
+ * The runtime services table is updated in
+ * efi_relocate_runtime_table()
+ */
+ if (map && efi_is_runtime_service_pointer(p))
+ continue;
+
+ debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__,
+ rel->info, *p, rel->offset);
+
+ switch (rel->info & R_MASK) {
+ case R_RELATIVE:
+#ifdef IS_RELA
+ newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE;
+#else
+ newaddr = *p - lastoff + offset;
+#endif
+ break;
+#ifdef R_ABSOLUTE
+ case R_ABSOLUTE: {
+ ulong symidx = rel->info >> SYM_INDEX;
+ extern struct dyn_sym __dyn_sym_start[];
+ newaddr = __dyn_sym_start[symidx].addr + offset;
+#ifdef IS_RELA
+ newaddr -= CONFIG_SYS_TEXT_BASE;
+#endif
+ break;
+ }
+#endif
+ default:
+ printf("%s: Unknown relocation type %llx\n",
+ __func__, rel->info & R_MASK);
+ continue;
+ }
+
+ /* Check if the relocation is inside bounds */
+ if (map && ((newaddr < map->virtual_start) ||
+ newaddr > (map->virtual_start +
+ (map->num_pages << EFI_PAGE_SHIFT)))) {
+ printf("%s: Relocation at %p is out of range (%lx)\n",
+ __func__, p, newaddr);
+ continue;
+ }
+
+ debug("%s: Setting %p to %lx\n", __func__, p, newaddr);
+ *p = newaddr;
+ flush_dcache_range((ulong)p & ~(EFI_CACHELINE_SIZE - 1),
+ ALIGN((ulong)&p[1], EFI_CACHELINE_SIZE));
+ }
+
+#ifndef IS_RELA
+ lastoff = offset;
+#endif
+
+ invalidate_icache_all();
+}
+
+/**
+ * efi_set_virtual_address_map() - change from physical to virtual mapping
+ *
+ * This function implements the SetVirtualAddressMap() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @memory_map_size: size of the virtual map
+ * @descriptor_size: size of an entry in the map
+ * @descriptor_version: version of the map entries
+ * @virtmap: virtual address mapping information
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_set_virtual_address_map(
+ efi_uintn_t memory_map_size,
+ efi_uintn_t descriptor_size,
+ uint32_t descriptor_version,
+ struct efi_mem_desc *virtmap)
+{
+ efi_uintn_t n = memory_map_size / descriptor_size;
+ efi_uintn_t i;
+ efi_status_t ret = EFI_INVALID_PARAMETER;
+ int rt_code_sections = 0;
+ struct efi_event *event;
+
+ EFI_ENTRY("%zx %zx %x %p", memory_map_size, descriptor_size,
+ descriptor_version, virtmap);
+
+ if (descriptor_version != EFI_MEMORY_DESCRIPTOR_VERSION ||
+ descriptor_size < sizeof(struct efi_mem_desc))
+ goto out;
+
+ efi_virtmap = virtmap;
+ efi_descriptor_size = descriptor_size;
+ efi_descriptor_count = n;
+
+ /*
+ * TODO:
+ * Further down we are cheating. While really we should implement
+ * SetVirtualAddressMap() events and ConvertPointer() to allow
+ * dynamically loaded drivers to expose runtime services, we don't
+ * today.
+ *
+ * So let's ensure we see exactly one single runtime section, as
+ * that is the built-in one. If we see more (or less), someone must
+ * have tried adding or removing to that which we don't support yet.
+ * In that case, let's better fail rather than expose broken runtime
+ * services.
+ */
+ for (i = 0; i < n; i++) {
+ struct efi_mem_desc *map = (void*)virtmap +
+ (descriptor_size * i);
+
+ if (map->type == EFI_RUNTIME_SERVICES_CODE)
+ rt_code_sections++;
+ }
+
+ if (rt_code_sections != 1) {
+ /*
+ * We expose exactly one single runtime code section, so
+ * something is definitely going wrong.
+ */
+ goto out;
+ }
+
+ /* Notify EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */
+ list_for_each_entry(event, &efi_events, link) {
+ if (event->notify_function)
+ EFI_CALL_VOID(event->notify_function(
+ event, event->notify_context));
+ }
+
+ /* Rebind mmio pointers */
+ for (i = 0; i < n; i++) {
+ struct efi_mem_desc *map = (void*)virtmap +
+ (descriptor_size * i);
+ struct list_head *lhandle;
+ efi_physical_addr_t map_start = map->physical_start;
+ efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT;
+ efi_physical_addr_t map_end = map_start + map_len;
+ u64 off = map->virtual_start - map_start;
+
+ /* Adjust all mmio pointers in this region */
+ list_for_each(lhandle, &efi_runtime_mmio) {
+ struct efi_runtime_mmio_list *lmmio;
+
+ lmmio = list_entry(lhandle,
+ struct efi_runtime_mmio_list,
+ link);
+ if ((map_start <= lmmio->paddr) &&
+ (map_end >= lmmio->paddr)) {
+ uintptr_t new_addr = lmmio->paddr + off;
+ *lmmio->ptr = (void *)new_addr;
+ }
+ }
+ if ((map_start <= (uintptr_t)systab.tables) &&
+ (map_end >= (uintptr_t)systab.tables)) {
+ char *ptr = (char *)systab.tables;
+
+ ptr += off;
+ systab.tables = (struct efi_configuration_table *)ptr;
+ }
+ }
+
+ /* Relocate the runtime. See TODO above */
+ for (i = 0; i < n; i++) {
+ struct efi_mem_desc *map;
+
+ map = (void*)virtmap + (descriptor_size * i);
+ if (map->type == EFI_RUNTIME_SERVICES_CODE) {
+ ulong new_offset = map->virtual_start -
+ map->physical_start + gd->relocaddr;
+
+ efi_relocate_runtime_table(new_offset);
+ efi_runtime_relocate(new_offset, map);
+ ret = EFI_SUCCESS;
+ goto out;
+ }
+ }
+
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_add_runtime_mmio() - add memory-mapped IO region
+ *
+ * This function adds a memory-mapped IO region to the memory map to make it
+ * available at runtime.
+ *
+ * @mmio_ptr: pointer to a pointer to the start of the memory-mapped
+ * IO region
+ * @len: size of the memory-mapped IO region
+ * Returns: status code
+ */
+efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
+{
+ struct efi_runtime_mmio_list *newmmio;
+ u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+ uint64_t addr = *(uintptr_t *)mmio_ptr;
+ efi_status_t ret;
+
+ ret = efi_add_memory_map(addr, pages, EFI_MMAP_IO, false);
+ if (ret != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ newmmio = calloc(1, sizeof(*newmmio));
+ if (!newmmio)
+ return EFI_OUT_OF_RESOURCES;
+ newmmio->ptr = mmio_ptr;
+ newmmio->paddr = *(uintptr_t *)mmio_ptr;
+ newmmio->len = len;
+ list_add_tail(&newmmio->link, &efi_runtime_mmio);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * In the second stage, U-Boot has disappeared. To isolate our runtime code
+ * that at this point still exists from the rest, we put it into a special
+ * section.
+ *
+ * !!WARNING!!
+ *
+ * This means that we can not rely on any code outside of this file in any
+ * function or variable below this line.
+ *
+ * Please keep everything fully self-contained and annotated with
+ * __efi_runtime and __efi_runtime_data markers.
+ */
+
+/*
+ * Relocate the EFI runtime stub to a different place. We need to call this
+ * the first time we expose the runtime interface to a user and on set virtual
+ * address map calls.
+ */
+
+/**
+ * efi_unimplemented() - replacement function, returns EFI_UNSUPPORTED
+ *
+ * This function is used after SetVirtualAddressMap() is called as replacement
+ * for services that are not available anymore due to constraints of the U-Boot
+ * implementation.
+ *
+ * Return: EFI_UNSUPPORTED
+ */
+static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_update_capsule() - process information from operating system
+ *
+ * This function implements the UpdateCapsule() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @capsule_header_array: pointer to array of virtual pointers
+ * @capsule_count: number of pointers in capsule_header_array
+ * @scatter_gather_list: pointer to arry of physical pointers
+ * Returns: status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 scatter_gather_list)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_query_capsule_caps() - check if capsule is supported
+ *
+ * This function implements the QueryCapsuleCapabilities() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @capsule_header_array: pointer to array of virtual pointers
+ * @capsule_count: number of pointers in capsule_header_array
+ * @maximum_capsule_size: maximum capsule size
+ * @reset_type: type of reset needed for capsule update
+ * Returns: status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 *maximum_capsule_size,
+ u32 *reset_type)
+{
+ return EFI_UNSUPPORTED;
+}
+
+struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
+ .hdr = {
+ .signature = EFI_RUNTIME_SERVICES_SIGNATURE,
+ .revision = EFI_SPECIFICATION_VERSION,
+ .headersize = sizeof(struct efi_runtime_services),
+ },
+ .get_time = &efi_get_time_boottime,
+ .set_time = &efi_set_time_boottime,
+ .get_wakeup_time = (void *)&efi_unimplemented,
+ .set_wakeup_time = (void *)&efi_unimplemented,
+ .set_virtual_address_map = &efi_set_virtual_address_map,
+ .convert_pointer = efi_convert_pointer,
+ .get_variable = efi_get_variable,
+ .get_next_variable_name = efi_get_next_variable_name,
+ .set_variable = efi_set_variable,
+ .get_next_high_mono_count = (void *)&efi_unimplemented,
+ .reset_system = &efi_reset_system_boottime,
+ .update_capsule = efi_update_capsule,
+ .query_capsule_caps = efi_query_capsule_caps,
+ .query_variable_info = efi_query_variable_info,
+};
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
new file mode 100644
index 00000000..de7b616c
--- /dev/null
+++ b/lib/efi_loader/efi_setup.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI setup code
+ *
+ * Copyright (c) 2016-2018 Alexander Graf et al.
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <efi_loader.h>
+
+#define OBJ_LIST_NOT_INITIALIZED 1
+
+static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
+
+/*
+ * Allow unaligned memory access.
+ *
+ * This routine is overridden by architectures providing this feature.
+ */
+void __weak allow_unaligned(void)
+{
+}
+
+/**
+ * efi_init_platform_lang() - define supported languages
+ *
+ * Set the PlatformLangCodes and PlatformLang variables.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_init_platform_lang(void)
+{
+ efi_status_t ret;
+ efi_uintn_t data_size = 0;
+ char *lang = CONFIG_EFI_PLATFORM_LANG_CODES;
+ char *pos;
+
+ /*
+ * Variable PlatformLangCodes defines the language codes that the
+ * machine can support.
+ */
+ ret = EFI_CALL(efi_set_variable(L"PlatformLangCodes",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(CONFIG_EFI_PLATFORM_LANG_CODES),
+ CONFIG_EFI_PLATFORM_LANG_CODES));
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /*
+ * Variable PlatformLang defines the language that the machine has been
+ * configured for.
+ */
+ ret = EFI_CALL(efi_get_variable(L"PlatformLang",
+ &efi_global_variable_guid,
+ NULL, &data_size, &pos));
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ /* The variable is already set. Do not change it. */
+ ret = EFI_SUCCESS;
+ goto out;
+ }
+
+ /*
+ * The list of supported languages is semicolon separated. Use the first
+ * language to initialize PlatformLang.
+ */
+ pos = strchr(lang, ';');
+ if (pos)
+ *pos = 0;
+
+ ret = EFI_CALL(efi_set_variable(L"PlatformLang",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 1 + strlen(lang), lang));
+out:
+ if (ret != EFI_SUCCESS)
+ printf("EFI: cannot initialize platform language settings\n");
+ return ret;
+}
+
+/**
+ * efi_init_obj_list() - Initialize and populate EFI object list
+ *
+ * Return: status code
+ */
+efi_status_t efi_init_obj_list(void)
+{
+ u64 os_indications_supported = 0; /* None */
+ efi_status_t ret = EFI_SUCCESS;
+
+ /* Initialize once only */
+ if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
+ return efi_obj_list_initialized;
+
+ /* Allow unaligned memory access */
+ allow_unaligned();
+
+ /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+ switch_to_non_secure_mode();
+
+ /* Initialize variable services */
+ ret = efi_init_variables();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Define supported languages */
+ ret = efi_init_platform_lang();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Indicate supported features */
+ ret = EFI_CALL(efi_set_variable(L"OsIndicationsSupported",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(os_indications_supported),
+ &os_indications_supported));
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Indicate supported runtime services */
+ ret = efi_init_runtime_supported();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Initialize system table */
+ ret = efi_initialize_system_table();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Initialize root node */
+ ret = efi_root_node_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Initialize EFI driver uclass */
+ ret = efi_driver_init();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = efi_console_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#ifdef CONFIG_PARTITIONS
+ ret = efi_disk_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#endif
+#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
+ ret = efi_gop_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#endif
+#ifdef CONFIG_NET
+ ret = efi_net_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#endif
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+ ret = efi_acpi_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#endif
+#ifdef CONFIG_GENERATE_SMBIOS_TABLE
+ ret = efi_smbios_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+#endif
+ ret = efi_watchdog_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /* Initialize EFI runtime services */
+ ret = efi_reset_system_init();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+out:
+ efi_obj_list_initialized = ret;
+ return ret;
+}
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
new file mode 100644
index 00000000..a8148849
--- /dev/null
+++ b/lib/efi_loader/efi_smbios.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application tables support
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <mapmem.h>
+#include <smbios.h>
+
+static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
+
+/*
+ * Install the SMBIOS table as a configuration table.
+ *
+ * @return status code
+ */
+efi_status_t efi_smbios_register(void)
+{
+ /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
+ u64 dmi_addr = U32_MAX;
+ efi_status_t ret;
+ void *dmi;
+
+ /* Reserve 4kiB page for SMBIOS */
+ ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+ EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
+
+ if (ret != EFI_SUCCESS) {
+ /* Could not find space in lowmem, use highmem instead */
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_RUNTIME_SERVICES_DATA, 1,
+ &dmi_addr);
+
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+
+ /*
+ * Generate SMBIOS tables - we know that efi_allocate_pages() returns
+ * a 4k-aligned address, so it is safe to assume that
+ * write_smbios_table() will write the table at that address.
+ *
+ * Note that on sandbox, efi_allocate_pages() unfortunately returns a
+ * pointer even though it uses a uint64_t type. Convert it.
+ */
+ assert(!(dmi_addr & 0xf));
+ dmi = (void *)(uintptr_t)dmi_addr;
+ write_smbios_table(map_to_sysmem(dmi));
+
+ /* And expose them to our EFI payload */
+ return efi_install_configuration_table(&smbios_guid, dmi);
+}
diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c
new file mode 100644
index 00000000..c700be87
--- /dev/null
+++ b/lib/efi_loader/efi_unicode_collation.c
@@ -0,0 +1,368 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI Unicode collation protocol
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <cp1250.h>
+#include <cp437.h>
+#include <efi_loader.h>
+
+/* Characters that may not be used in FAT 8.3 file names */
+static const char illegal[] = "+,<=>:;\"/\\|?*[]\x7f";
+
+/*
+ * EDK2 assumes codepage 1250 when creating FAT 8.3 file names.
+ * Linux defaults to codepage 437 for FAT 8.3 file names.
+ */
+#if CONFIG_FAT_DEFAULT_CODEPAGE == 1250
+/* Unicode code points for code page 1250 characters 0x80 - 0xff */
+static const u16 codepage[] = CP1250;
+#else
+/* Unicode code points for code page 437 characters 0x80 - 0xff */
+static const u16 codepage[] = CP437;
+#endif
+
+/* GUID of the EFI_UNICODE_COLLATION_PROTOCOL2 */
+const efi_guid_t efi_guid_unicode_collation_protocol2 =
+ EFI_UNICODE_COLLATION_PROTOCOL2_GUID;
+
+/**
+ * efi_stri_coll() - compare utf-16 strings case-insenitively
+ *
+ * @this: unicode collation protocol instance
+ * @s1: first string
+ * @s2: second string
+ *
+ * This function implements the StriColl() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: 0: s1 == s2, > 0: s1 > s2, < 0: s1 < s2
+ */
+static efi_intn_t EFIAPI efi_stri_coll(
+ struct efi_unicode_collation_protocol *this, u16 *s1, u16 *s2)
+{
+ s32 c1, c2;
+ efi_intn_t ret = 0;
+
+ EFI_ENTRY("%p, %ls, %ls", this, s1, s2);
+ for (; *s1 | *s2; ++s1, ++s2) {
+ c1 = utf_to_upper(*s1);
+ c2 = utf_to_upper(*s2);
+ if (c1 < c2) {
+ ret = -1;
+ goto out;
+ } else if (c1 > c2) {
+ ret = 1;
+ goto out;
+ }
+ }
+out:
+ EFI_EXIT(EFI_SUCCESS);
+ return ret;
+}
+
+/**
+ * next_lower() - get next codepoint converted to lower case
+ *
+ * @string: pointer to u16 string, on return advanced by one codepoint
+ * Return: first codepoint of string converted to lower case
+ */
+static s32 next_lower(const u16 **string)
+{
+ return utf_to_lower(utf16_get(string));
+}
+
+/**
+ * metai_match() - compare utf-16 string with a pattern string case-insenitively
+ *
+ * @string: string to compare
+ * @pattern: pattern string
+ *
+ * The pattern string may use these:
+ * - * matches >= 0 characters
+ * - ? matches 1 character
+ * - [<char1><char2>...<charN>] match any character in the set
+ * - [<char1>-<char2>] matches any character in the range
+ *
+ * This function is called my efi_metai_match().
+ *
+ * For '*' pattern searches this function calls itself recursively.
+ * Performance-wise this is suboptimal, especially for multiple '*' wildcards.
+ * But it results in simple code.
+ *
+ * Return: true if the string is matched.
+ */
+static bool metai_match(const u16 *string, const u16 *pattern)
+{
+ s32 first, s, p;
+
+ for (; *string && *pattern;) {
+ const u16 *string_old = string;
+
+ s = next_lower(&string);
+ p = next_lower(&pattern);
+
+ switch (p) {
+ case '*':
+ /* Match 0 or more characters */
+ for (;; s = next_lower(&string)) {
+ if (metai_match(string_old, pattern))
+ return true;
+ if (!s)
+ return false;
+ string_old = string;
+ }
+ case '?':
+ /* Match any one character */
+ break;
+ case '[':
+ /* Match any character in the set */
+ p = next_lower(&pattern);
+ first = p;
+ if (first == ']')
+ /* Empty set */
+ return false;
+ p = next_lower(&pattern);
+ if (p == '-') {
+ /* Range */
+ p = next_lower(&pattern);
+ if (s < first || s > p)
+ return false;
+ p = next_lower(&pattern);
+ if (p != ']')
+ return false;
+ } else {
+ /* Set */
+ bool hit = false;
+
+ if (s == first)
+ hit = true;
+ for (; p && p != ']';
+ p = next_lower(&pattern)) {
+ if (p == s)
+ hit = true;
+ }
+ if (!hit || p != ']')
+ return false;
+ }
+ break;
+ default:
+ /* Match one character */
+ if (p != s)
+ return false;
+ }
+ }
+ if (!*pattern && !*string)
+ return true;
+ return false;
+}
+
+/**
+ * efi_metai_match() - compare utf-16 string with a pattern string
+ * case-insenitively
+ *
+ * @this: unicode collation protocol instance
+ * @s: string to compare
+ * @p: pattern string
+ *
+ * The pattern string may use these:
+ * - * matches >= 0 characters
+ * - ? matches 1 character
+ * - [<char1><char2>...<charN>] match any character in the set
+ * - [<char1>-<char2>] matches any character in the range
+ *
+ * This function implements the MetaMatch() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ *
+ * Return: true if the string is matched.
+ */
+static bool EFIAPI efi_metai_match(struct efi_unicode_collation_protocol *this,
+ const u16 *string, const u16 *pattern)
+{
+ bool ret;
+
+ EFI_ENTRY("%p, %ls, %ls", this, string, pattern);
+ ret = metai_match(string, pattern);
+ EFI_EXIT(EFI_SUCCESS);
+ return ret;
+}
+
+/**
+ * efi_str_lwr() - convert to lower case
+ *
+ * @this: unicode collation protocol instance
+ * @string: string to convert
+ * @p: pattern string
+ *
+ * The conversion is done in place. As long as upper and lower letters use the
+ * same number of words this does not pose a problem.
+ *
+ * This function implements the StrLwr() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ */
+static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
+ u16 *string)
+{
+ EFI_ENTRY("%p, %ls", this, string);
+ for (; *string; ++string)
+ *string = utf_to_lower(*string);
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_str_upr() - convert to upper case
+ *
+ * @this: unicode collation protocol instance
+ * @string: string to convert
+ * @p: pattern string
+ *
+ * The conversion is done in place. As long as upper and lower letters use the
+ * same number of words this does not pose a problem.
+ *
+ * This function implements the StrUpr() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ */
+static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
+ u16 *string)
+{
+ EFI_ENTRY("%p, %ls", this, string);
+ for (; *string; ++string)
+ *string = utf_to_upper(*string);
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_fat_to_str() - convert an 8.3 file name from an OEM codepage to Unicode
+ *
+ * @this: unicode collation protocol instance
+ * @fat_size: size of the string to convert
+ * @fat: string to convert
+ * @string: converted string
+ *
+ * This function implements the FatToStr() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ */
+static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
+ efi_uintn_t fat_size, char *fat, u16 *string)
+{
+ efi_uintn_t i;
+ u16 c;
+
+ EFI_ENTRY("%p, %zu, %s, %p", this, fat_size, fat, string);
+ for (i = 0; i < fat_size; ++i) {
+ c = (unsigned char)fat[i];
+ if (c > 0x80)
+ c = codepage[i - 0x80];
+ string[i] = c;
+ if (!c)
+ break;
+ }
+ string[i] = 0;
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_fat_to_str() - convert a utf-16 string to legal characters for a FAT
+ * file name in an OEM code page
+ *
+ * @this: unicode collation protocol instance
+ * @string: Unicode string to convert
+ * @fat_size: size of the target buffer
+ * @fat: converted string
+ *
+ * This function implements the StrToFat() service of the
+ * EFI_UNICODE_COLLATION_PROTOCOL.
+ *
+ * Return: true if an illegal character was substituted by '_'.
+ */
+static bool EFIAPI efi_str_to_fat(struct efi_unicode_collation_protocol *this,
+ const u16 *string, efi_uintn_t fat_size,
+ char *fat)
+{
+ efi_uintn_t i;
+ s32 c;
+ bool ret = false;
+
+ EFI_ENTRY("%p, %ls, %zu, %p", this, string, fat_size, fat);
+ for (i = 0; i < fat_size;) {
+ c = utf16_get(&string);
+ switch (c) {
+ /* Ignore period and space */
+ case '.':
+ case ' ':
+ continue;
+ case 0:
+ break;
+ }
+ c = utf_to_upper(c);
+ if (c >= 0x80) {
+ int j;
+
+ /* Look for codepage translation */
+ for (j = 0; j < 0x80; ++j) {
+ if (c == codepage[j]) {
+ c = j + 0x80;
+ break;
+ }
+ }
+ if (j >= 0x80) {
+ c = '_';
+ ret = true;
+ }
+ } else if (c && (c < 0x20 || strchr(illegal, c))) {
+ c = '_';
+ ret = true;
+ }
+
+ fat[i] = c;
+ if (!c)
+ break;
+ ++i;
+ }
+ EFI_EXIT(EFI_SUCCESS);
+ return ret;
+}
+
+const struct efi_unicode_collation_protocol efi_unicode_collation_protocol2 = {
+ .stri_coll = efi_stri_coll,
+ .metai_match = efi_metai_match,
+ .str_lwr = efi_str_lwr,
+ .str_upr = efi_str_upr,
+ .fat_to_str = efi_fat_to_str,
+ .str_to_fat = efi_str_to_fat,
+ .supported_languages = "en",
+};
+
+/*
+ * In EFI 1.10 a version of the Unicode collation protocol using ISO 639-2
+ * language codes existed. This protocol is not part of the UEFI specification
+ * any longer. Unfortunately it is required to run the UEFI Self Certification
+ * Test (SCT) II, version 2.6, 2017. So we implement it here for the sole
+ * purpose of running the SCT. It can be removed when a compliant SCT is
+ * available.
+ */
+#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
+
+/* GUID of the EFI_UNICODE_COLLATION_PROTOCOL */
+const efi_guid_t efi_guid_unicode_collation_protocol =
+ EFI_UNICODE_COLLATION_PROTOCOL_GUID;
+
+const struct efi_unicode_collation_protocol efi_unicode_collation_protocol = {
+ .stri_coll = efi_stri_coll,
+ .metai_match = efi_metai_match,
+ .str_lwr = efi_str_lwr,
+ .str_upr = efi_str_upr,
+ .fat_to_str = efi_fat_to_str,
+ .str_to_fat = efi_str_to_fat,
+ /* ISO 639-2 language code */
+ .supported_languages = "eng",
+};
+
+#endif
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
new file mode 100644
index 00000000..c316bdfe
--- /dev/null
+++ b/lib/efi_loader/efi_variable.c
@@ -0,0 +1,643 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI utils
+ *
+ * Copyright (c) 2017 Rob Clark
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <env_internal.h>
+#include <hexdump.h>
+#include <malloc.h>
+#include <search.h>
+#include <u-boot/crc.h>
+
+#define READ_ONLY BIT(31)
+
+/*
+ * Mapping between EFI variables and u-boot variables:
+ *
+ * efi_$guid_$varname = {attributes}(type)value
+ *
+ * For example:
+ *
+ * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
+ * "{ro,boot,run}(blob)0000000000000000"
+ * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
+ * "(blob)00010000"
+ *
+ * The attributes are a comma separated list of these possible
+ * attributes:
+ *
+ * + ro - read-only
+ * + boot - boot-services access
+ * + run - runtime access
+ *
+ * NOTE: with current implementation, no variables are available after
+ * ExitBootServices, and all are persisted (if possible).
+ *
+ * If not specified, the attributes default to "{boot}".
+ *
+ * The required type is one of:
+ *
+ * + utf8 - raw utf8 string
+ * + blob - arbitrary length hex string
+ *
+ * Maybe a utf16 type would be useful to for a string value to be auto
+ * converted to utf16?
+ */
+
+#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
+
+/**
+ * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
+ * variable name
+ *
+ * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
+ * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
+ * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
+ *
+ * @native: pointer to pointer to U-Boot variable name
+ * @variable_name: UEFI variable name
+ * @vendor: vendor GUID
+ * Return: status code
+ */
+static efi_status_t efi_to_native(char **native, const u16 *variable_name,
+ const efi_guid_t *vendor)
+{
+ size_t len;
+ char *pos;
+
+ len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
+ *native = malloc(len);
+ if (!*native)
+ return EFI_OUT_OF_RESOURCES;
+
+ pos = *native;
+ pos += sprintf(pos, "efi_%pUl_", vendor);
+ utf16_utf8_strcpy(&pos, variable_name);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * prefix() - skip over prefix
+ *
+ * Skip over a prefix string.
+ *
+ * @str: string with prefix
+ * @prefix: prefix string
+ * Return: string without prefix, or NULL if prefix not found
+ */
+static const char *prefix(const char *str, const char *prefix)
+{
+ size_t n = strlen(prefix);
+ if (!strncmp(prefix, str, n))
+ return str + n;
+ return NULL;
+}
+
+/**
+ * parse_attr() - decode attributes part of variable value
+ *
+ * Convert the string encoded attributes of a UEFI variable to a bit mask.
+ * TODO: Several attributes are not supported.
+ *
+ * @str: value of U-Boot variable
+ * @attrp: pointer to UEFI attributes
+ * Return: pointer to remainder of U-Boot variable value
+ */
+static const char *parse_attr(const char *str, u32 *attrp)
+{
+ u32 attr = 0;
+ char sep = '{';
+
+ if (*str != '{') {
+ *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ return str;
+ }
+
+ while (*str == sep) {
+ const char *s;
+
+ str++;
+
+ if ((s = prefix(str, "ro"))) {
+ attr |= READ_ONLY;
+ } else if ((s = prefix(str, "nv"))) {
+ attr |= EFI_VARIABLE_NON_VOLATILE;
+ } else if ((s = prefix(str, "boot"))) {
+ attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ } else if ((s = prefix(str, "run"))) {
+ attr |= EFI_VARIABLE_RUNTIME_ACCESS;
+ } else {
+ printf("invalid attribute: %s\n", str);
+ break;
+ }
+
+ str = s;
+ sep = ',';
+ }
+
+ str++;
+
+ *attrp = attr;
+
+ return str;
+}
+
+/**
+ * efi_get_variable() - retrieve value of a UEFI variable
+ *
+ * This function implements the GetVariable runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer to which the variable value is copied
+ * @data: buffer to which the variable value is copied
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
+ const efi_guid_t *vendor, u32 *attributes,
+ efi_uintn_t *data_size, void *data)
+{
+ char *native_name;
+ efi_status_t ret;
+ unsigned long in_size;
+ const char *val, *s;
+ u32 attr;
+
+ EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
+ data_size, data);
+
+ if (!variable_name || !vendor || !data_size)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ ret = efi_to_native(&native_name, variable_name, vendor);
+ if (ret)
+ return EFI_EXIT(ret);
+
+ EFI_PRINT("get '%s'\n", native_name);
+
+ val = env_get(native_name);
+ free(native_name);
+ if (!val)
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ val = parse_attr(val, &attr);
+
+ in_size = *data_size;
+
+ if ((s = prefix(val, "(blob)"))) {
+ size_t len = strlen(s);
+
+ /* number of hexadecimal digits must be even */
+ if (len & 1)
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+
+ /* two characters per byte: */
+ len /= 2;
+ *data_size = len;
+
+ if (in_size < len) {
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+
+ if (!data)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ if (hex2bin(data, s, len))
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+
+ EFI_PRINT("got value: \"%s\"\n", s);
+ } else if ((s = prefix(val, "(utf8)"))) {
+ unsigned len = strlen(s) + 1;
+
+ *data_size = len;
+
+ if (in_size < len) {
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+
+ if (!data)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ memcpy(data, s, len);
+ ((char *)data)[len] = '\0';
+
+ EFI_PRINT("got value: \"%s\"\n", (char *)data);
+ } else {
+ EFI_PRINT("invalid value: '%s'\n", val);
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+ }
+
+out:
+ if (attributes)
+ *attributes = attr & EFI_VARIABLE_MASK;
+
+ return EFI_EXIT(ret);
+}
+
+static char *efi_variables_list;
+static char *efi_cur_variable;
+
+/**
+ * parse_uboot_variable() - parse a u-boot variable and get uefi-related
+ * information
+ * @variable: whole data of u-boot variable (ie. name=value)
+ * @variable_name_size: size of variable_name buffer in byte
+ * @variable_name: name of uefi variable in u16, null-terminated
+ * @vendor: vendor's guid
+ * @attributes: attributes
+ *
+ * A uefi variable is encoded into a u-boot variable as described above.
+ * This function parses such a u-boot variable and retrieve uefi-related
+ * information into respective parameters. In return, variable_name_size
+ * is the size of variable name including NULL.
+ *
+ * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
+ * the entire variable list has been returned,
+ * otherwise non-zero status code
+ */
+static efi_status_t parse_uboot_variable(char *variable,
+ efi_uintn_t *variable_name_size,
+ u16 *variable_name,
+ const efi_guid_t *vendor,
+ u32 *attributes)
+{
+ char *guid, *name, *end, c;
+ unsigned long name_len;
+ u16 *p;
+
+ guid = strchr(variable, '_');
+ if (!guid)
+ return EFI_INVALID_PARAMETER;
+ guid++;
+ name = strchr(guid, '_');
+ if (!name)
+ return EFI_INVALID_PARAMETER;
+ name++;
+ end = strchr(name, '=');
+ if (!end)
+ return EFI_INVALID_PARAMETER;
+
+ name_len = end - name;
+ if (*variable_name_size < (name_len + 1)) {
+ *variable_name_size = name_len + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ end++; /* point to value */
+
+ /* variable name */
+ p = variable_name;
+ utf8_utf16_strncpy(&p, name, name_len);
+ variable_name[name_len] = 0;
+ *variable_name_size = name_len + 1;
+
+ /* guid */
+ c = *(name - 1);
+ *(name - 1) = '\0'; /* guid need be null-terminated here */
+ uuid_str_to_bin(guid, (unsigned char *)vendor, UUID_STR_FORMAT_GUID);
+ *(name - 1) = c;
+
+ /* attributes */
+ parse_attr(end, attributes);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_get_next_variable_name() - enumerate the current variable names
+ *
+ * @variable_name_size: size of variable_name buffer in byte
+ * @variable_name: name of uefi variable's name in u16
+ * @vendor: vendor's guid
+ *
+ * This function implements the GetNextVariableName service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
+ u16 *variable_name,
+ const efi_guid_t *vendor)
+{
+ char *native_name, *variable;
+ ssize_t name_len, list_len;
+ char regex[256];
+ char * const regexlist[] = {regex};
+ u32 attributes;
+ int i;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
+
+ if (!variable_name_size || !variable_name || !vendor)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ if (variable_name[0]) {
+ /* check null-terminated string */
+ for (i = 0; i < *variable_name_size; i++)
+ if (!variable_name[i])
+ break;
+ if (i >= *variable_name_size)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* search for the last-returned variable */
+ ret = efi_to_native(&native_name, variable_name, vendor);
+ if (ret)
+ return EFI_EXIT(ret);
+
+ name_len = strlen(native_name);
+ for (variable = efi_variables_list; variable && *variable;) {
+ if (!strncmp(variable, native_name, name_len) &&
+ variable[name_len] == '=')
+ break;
+
+ variable = strchr(variable, '\n');
+ if (variable)
+ variable++;
+ }
+
+ free(native_name);
+ if (!(variable && *variable))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* next variable */
+ variable = strchr(variable, '\n');
+ if (variable)
+ variable++;
+ if (!(variable && *variable))
+ return EFI_EXIT(EFI_NOT_FOUND);
+ } else {
+ /*
+ *new search: free a list used in the previous search
+ */
+ free(efi_variables_list);
+ efi_variables_list = NULL;
+ efi_cur_variable = NULL;
+
+ snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
+ list_len = hexport_r(&env_htab, '\n',
+ H_MATCH_REGEX | H_MATCH_KEY,
+ &efi_variables_list, 0, 1, regexlist);
+ /* 1 indicates that no match was found */
+ if (list_len <= 1)
+ return EFI_EXIT(EFI_NOT_FOUND);
+
+ variable = efi_variables_list;
+ }
+
+ ret = parse_uboot_variable(variable, variable_name_size, variable_name,
+ vendor, &attributes);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_set_variable() - set value of a UEFI variable
+ *
+ * This function implements the SetVariable runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer with the variable value
+ * @data: buffer with the variable value
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
+ const efi_guid_t *vendor, u32 attributes,
+ efi_uintn_t data_size, const void *data)
+{
+ char *native_name = NULL, *val = NULL, *s;
+ const char *old_val;
+ size_t old_size;
+ efi_status_t ret = EFI_SUCCESS;
+ u32 attr;
+
+ EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
+ data_size, data);
+
+ if (!variable_name || !*variable_name || !vendor ||
+ ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
+ !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_to_native(&native_name, variable_name, vendor);
+ if (ret)
+ goto out;
+
+ old_val = env_get(native_name);
+ if (old_val) {
+ old_val = parse_attr(old_val, &attr);
+
+ /* check read-only first */
+ if (attr & READ_ONLY) {
+ ret = EFI_WRITE_PROTECTED;
+ goto out;
+ }
+
+ if ((data_size == 0 &&
+ !(attributes & EFI_VARIABLE_APPEND_WRITE)) ||
+ !attributes) {
+ /* delete the variable: */
+ env_set(native_name, NULL);
+ ret = EFI_SUCCESS;
+ goto out;
+ }
+
+ /* attributes won't be changed */
+ if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if (attributes & EFI_VARIABLE_APPEND_WRITE) {
+ if (!prefix(old_val, "(blob)")) {
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+ old_size = strlen(old_val);
+ } else {
+ old_size = 0;
+ }
+ } else {
+ if (data_size == 0 || !attributes ||
+ (attributes & EFI_VARIABLE_APPEND_WRITE)) {
+ /*
+ * Trying to delete or to update a non-existent
+ * variable.
+ */
+ ret = EFI_NOT_FOUND;
+ goto out;
+ }
+
+ old_size = 0;
+ }
+
+ val = malloc(old_size + 2 * data_size
+ + strlen("{ro,run,boot,nv}(blob)") + 1);
+ if (!val) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ s = val;
+
+ /* store attributes */
+ attributes &= (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS);
+ s += sprintf(s, "{");
+ while (attributes) {
+ u32 attr = 1 << (ffs(attributes) - 1);
+
+ if (attr == EFI_VARIABLE_NON_VOLATILE)
+ s += sprintf(s, "nv");
+ else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
+ s += sprintf(s, "boot");
+ else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
+ s += sprintf(s, "run");
+
+ attributes &= ~attr;
+ if (attributes)
+ s += sprintf(s, ",");
+ }
+ s += sprintf(s, "}");
+
+ if (old_size)
+ /* APPEND_WRITE */
+ s += sprintf(s, old_val);
+ else
+ s += sprintf(s, "(blob)");
+
+ /* store payload: */
+ s = bin2hex(s, data, data_size);
+ *s = '\0';
+
+ EFI_PRINT("setting: %s=%s\n", native_name, val);
+
+ if (env_set(native_name, val))
+ ret = EFI_DEVICE_ERROR;
+
+out:
+ free(native_name);
+ free(val);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_query_variable_info() - get information about EFI variables
+ *
+ * This function implements the QueryVariableInfo() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @attributes: bitmask to select variables to be
+ * queried
+ * @maximum_variable_storage_size: maximum size of storage area for the
+ * selected variable types
+ * @remaining_variable_storage_size: remaining size of storage are for the
+ * selected variable types
+ * @maximum_variable_size: maximum size of a variable of the
+ * selected type
+ * Returns: status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
+ u32 attributes,
+ u64 *maximum_variable_storage_size,
+ u64 *remaining_variable_storage_size,
+ u64 *maximum_variable_size)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_get_variable_runtime() - runtime implementation of GetVariable()
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer to which the variable value is copied
+ * @data: buffer to which the variable value is copied
+ * Return: status code
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size, void *data)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_get_next_variable_name_runtime() - runtime implementation of
+ * GetNextVariable()
+ *
+ * @variable_name_size: size of variable_name buffer in byte
+ * @variable_name: name of uefi variable's name in u16
+ * @vendor: vendor's guid
+ * Return: status code
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
+ u16 *variable_name, const efi_guid_t *vendor)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_set_variable_runtime() - runtime implementation of SetVariable()
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer with the variable value
+ * @data: buffer with the variable value
+ * Return: status code
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
+ u32 attributes, efi_uintn_t data_size,
+ const void *data)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
+ */
+void efi_variables_boot_exit_notify(void)
+{
+ efi_runtime_services.get_variable = efi_get_variable_runtime;
+ efi_runtime_services.get_next_variable_name =
+ efi_get_next_variable_name_runtime;
+ efi_runtime_services.set_variable = efi_set_variable_runtime;
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
+}
+
+/**
+ * efi_init_variables() - initialize variable services
+ *
+ * Return: status code
+ */
+efi_status_t efi_init_variables(void)
+{
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c
new file mode 100644
index 00000000..6f69b76e
--- /dev/null
+++ b/lib/efi_loader/efi_watchdog.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI watchdog
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+
+/* Conversion factor from seconds to multiples of 100ns */
+#define EFI_SECONDS_TO_100NS 10000000ULL
+
+static struct efi_event *watchdog_timer_event;
+
+/*
+ * Reset the system when the watchdog event is notified.
+ *
+ * @event: the watchdog event
+ * @context: not used
+ */
+static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event,
+ void *context)
+{
+ EFI_ENTRY("%p, %p", event, context);
+
+ printf("\nEFI: Watchdog timeout\n");
+ EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD,
+ EFI_SUCCESS, 0, NULL));
+
+ EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/*
+ * Reset the watchdog timer.
+ *
+ * This function is used by the SetWatchdogTimer service.
+ *
+ * @timeout: seconds before reset by watchdog
+ * @return: status code
+ */
+efi_status_t efi_set_watchdog(unsigned long timeout)
+{
+ efi_status_t r;
+
+ if (timeout)
+ /* Reset watchdog */
+ r = efi_set_timer(watchdog_timer_event, EFI_TIMER_RELATIVE,
+ EFI_SECONDS_TO_100NS * timeout);
+ else
+ /* Deactivate watchdog */
+ r = efi_set_timer(watchdog_timer_event, EFI_TIMER_STOP, 0);
+ return r;
+}
+
+/*
+ * Initialize the EFI watchdog.
+ *
+ * This function is called by efi_init_obj_list()
+ */
+efi_status_t efi_watchdog_register(void)
+{
+ efi_status_t r;
+
+ /*
+ * Create a timer event.
+ */
+ r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ efi_watchdog_timer_notify, NULL, NULL,
+ &watchdog_timer_event);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to register watchdog event\n");
+ return r;
+ }
+ /*
+ * The UEFI standard requires that the watchdog timer is set to five
+ * minutes when invoking an EFI boot option.
+ *
+ * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
+ * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
+ */
+ r = efi_set_watchdog(300);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: Failed to set watchdog timer\n");
+ return r;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
new file mode 100644
index 00000000..9ae2ee33
--- /dev/null
+++ b/lib/efi_loader/helloworld.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI hello world
+ *
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * This program demonstrates calling a boottime service.
+ * It writes a greeting and the load options to the console.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+static const efi_guid_t fdt_guid = EFI_FDT_GUID;
+static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
+static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systable)
+{
+ struct efi_simple_text_output_protocol *con_out = systable->con_out;
+ struct efi_boot_services *boottime = systable->boottime;
+ struct efi_loaded_image *loaded_image;
+ efi_status_t ret;
+ efi_uintn_t i;
+ u16 rev[] = L"0.0.0";
+
+ /* UEFI requires CR LF */
+ con_out->output_string(con_out, L"Hello, world!\r\n");
+
+ /* Print the revision number */
+ rev[0] = (systable->hdr.revision >> 16) + '0';
+ rev[4] = systable->hdr.revision & 0xffff;
+ for (; rev[4] >= 10;) {
+ rev[4] -= 10;
+ ++rev[2];
+ }
+ /* Third digit is only to be shown if non-zero */
+ if (rev[4])
+ rev[4] += '0';
+ else
+ rev[3] = 0;
+
+ con_out->output_string(con_out, L"Running on UEFI ");
+ con_out->output_string(con_out, rev);
+ con_out->output_string(con_out, L"\r\n");
+
+ /* Get the loaded image protocol */
+ ret = boottime->handle_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Cannot open loaded image protocol\r\n");
+ goto out;
+ }
+ /* Find configuration tables */
+ for (i = 0; i < systable->nr_tables; ++i) {
+ if (!memcmp(&systable->tables[i].guid, &fdt_guid,
+ sizeof(efi_guid_t)))
+ con_out->output_string
+ (con_out, L"Have device tree\r\n");
+ if (!memcmp(&systable->tables[i].guid, &acpi_guid,
+ sizeof(efi_guid_t)))
+ con_out->output_string
+ (con_out, L"Have ACPI 2.0 table\r\n");
+ if (!memcmp(&systable->tables[i].guid, &smbios_guid,
+ sizeof(efi_guid_t)))
+ con_out->output_string
+ (con_out, L"Have SMBIOS table\r\n");
+ }
+ /* Output the load options */
+ con_out->output_string(con_out, L"Load options: ");
+ if (loaded_image->load_options_size && loaded_image->load_options)
+ con_out->output_string(con_out,
+ (u16 *)loaded_image->load_options);
+ else
+ con_out->output_string(con_out, L"<none>");
+ con_out->output_string(con_out, L"\r\n");
+
+out:
+ boottime->exit(handle, ret, 0, NULL);
+
+ /* We should never arrive here */
+ return ret;
+}
diff --git a/lib/efi_selftest/.gitignore b/lib/efi_selftest/.gitignore
new file mode 100644
index 00000000..293a17b8
--- /dev/null
+++ b/lib/efi_selftest/.gitignore
@@ -0,0 +1,4 @@
+efi_miniapp_file_image_exit.h
+efi_miniapp_file_image_return.h
+*.efi
+*.so
diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig
new file mode 100644
index 00000000..d20f5899
--- /dev/null
+++ b/lib/efi_selftest/Kconfig
@@ -0,0 +1,9 @@
+config CMD_BOOTEFI_SELFTEST
+ bool "UEFI unit tests"
+ depends on CMD_BOOTEFI
+ imply FAT
+ imply FAT_WRITE
+ help
+ This adds a UEFI test application to U-Boot that can be executed
+ via the 'bootefi selftest' command. It provides extended tests of
+ the UEFI API implementation.
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
new file mode 100644
index 00000000..487cb4c6
--- /dev/null
+++ b/lib/efi_selftest/Makefile
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+asflags-y += -DHOST_ARCH="$(HOST_ARCH)"
+ccflags-y += -DHOST_ARCH="$(HOST_ARCH)"
+
+CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
+
+obj-y += \
+efi_selftest.o \
+efi_selftest_bitblt.o \
+efi_selftest_config_table.o \
+efi_selftest_controllers.o \
+efi_selftest_console.o \
+efi_selftest_crc32.o \
+efi_selftest_devicepath_util.o \
+efi_selftest_events.o \
+efi_selftest_event_groups.o \
+efi_selftest_exitbootservices.o \
+efi_selftest_gop.o \
+efi_selftest_loaded_image.o \
+efi_selftest_manageprotocols.o \
+efi_selftest_memory.o \
+efi_selftest_open_protocol.o \
+efi_selftest_register_notify.o \
+efi_selftest_set_virtual_address_map.o \
+efi_selftest_snp.o \
+efi_selftest_textinput.o \
+efi_selftest_textinputex.o \
+efi_selftest_textoutput.o \
+efi_selftest_tpl.o \
+efi_selftest_util.o \
+efi_selftest_variables.o \
+efi_selftest_variables_runtime.o \
+efi_selftest_watchdog.o
+
+obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_selftest_devicepath.o
+obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += \
+efi_selftest_unicode_collation.o
+
+obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
+obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o
+obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o
+
+ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
+obj-y += efi_selftest_fdt.o
+endif
+
+ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
+obj-y += efi_selftest_block_device.o
+endif
+
+# TODO: As of v2019.10 the relocation code for the EFI application cannot
+# be built on ARMv7-M.
+ifeq ($(CONFIG_CPU_V7M),)
+
+obj-y += \
+efi_selftest_exception.o \
+efi_selftest_loadimage.o \
+efi_selftest_startimage_exit.o \
+efi_selftest_startimage_return.o
+
+targets += \
+efi_miniapp_file_image_exception.h \
+efi_miniapp_file_image_exit.h \
+efi_miniapp_file_image_return.h \
+efi_selftest_miniapp_exception.efi \
+efi_selftest_miniapp_exit.efi \
+efi_selftest_miniapp_return.efi
+
+$(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi
+ $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \
+ $(obj)/efi_miniapp_file_image_exception.h
+
+$(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
+ $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
+ $(obj)/efi_miniapp_file_image_exit.h
+
+$(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
+ $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
+ $(obj)/efi_miniapp_file_image_return.h
+
+$(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
+
+$(obj)/efi_selftest_exception.o: $(obj)/efi_miniapp_file_image_exception.h
+
+$(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
+
+$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
+
+endif
diff --git a/lib/efi_selftest/efi_freestanding.c b/lib/efi_selftest/efi_freestanding.c
new file mode 100644
index 00000000..4b6c27e9
--- /dev/null
+++ b/lib/efi_selftest/efi_freestanding.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Library for freestanding binary
+ *
+ * Copyright 2019, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * GCC requires that freestanding programs provide memcpy(), memmove(),
+ * memset(), and memcmp().
+ */
+
+#include "../efi_loader/efi_freestanding.c"
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
new file mode 100644
index 00000000..5b01610e
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+/* Constants for test step bitmap */
+#define EFI_ST_SETUP 1
+#define EFI_ST_EXECUTE 2
+#define EFI_ST_TEARDOWN 4
+
+static const struct efi_system_table *systable;
+static const struct efi_boot_services *boottime;
+static const struct efi_runtime_services *runtime;
+static efi_handle_t handle;
+static u16 reset_message[] = L"Selftest completed";
+static int *setup_status;
+
+/*
+ * Exit the boot services.
+ *
+ * The size of the memory map is determined.
+ * Pool memory is allocated to copy the memory map.
+ * The memory map is copied and the map key is obtained.
+ * The map key is used to exit the boot services.
+ */
+void efi_st_exit_boot_services(void)
+{
+ efi_uintn_t map_size = 0;
+ efi_uintn_t map_key;
+ efi_uintn_t desc_size;
+ u32 desc_version;
+ efi_status_t ret;
+ struct efi_mem_desc *memory_map;
+
+ ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+ &desc_version);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error(
+ "GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
+ return;
+ }
+ /* Allocate extra space for newly allocated memory */
+ map_size += sizeof(struct efi_mem_desc);
+ ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+ (void **)&memory_map);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool did not return EFI_SUCCESS\n");
+ return;
+ }
+ ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+ &desc_size, &desc_version);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetMemoryMap did not return EFI_SUCCESS\n");
+ return;
+ }
+ ret = boottime->exit_boot_services(handle, map_key);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ExitBootServices did not return EFI_SUCCESS\n");
+ return;
+ }
+ efi_st_printc(EFI_WHITE, "\nBoot services terminated\n");
+}
+
+/*
+ * Set up a test.
+ *
+ * @test the test to be executed
+ * @failures counter that will be incremented if a failure occurs
+ * @return EFI_ST_SUCCESS for success
+ */
+static int setup(struct efi_unit_test *test, unsigned int *failures)
+{
+ int ret;
+
+ if (!test->setup)
+ return EFI_ST_SUCCESS;
+ efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
+ ret = test->setup(handle, systable);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("Setting up '%s' failed\n", test->name);
+ ++*failures;
+ } else {
+ efi_st_printc(EFI_LIGHTGREEN,
+ "Setting up '%s' succeeded\n", test->name);
+ }
+ return ret;
+}
+
+/*
+ * Execute a test.
+ *
+ * @test the test to be executed
+ * @failures counter that will be incremented if a failure occurs
+ * @return EFI_ST_SUCCESS for success
+ */
+static int execute(struct efi_unit_test *test, unsigned int *failures)
+{
+ int ret;
+
+ if (!test->execute)
+ return EFI_ST_SUCCESS;
+ efi_st_printc(EFI_LIGHTBLUE, "\nExecuting '%s'\n", test->name);
+ ret = test->execute();
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("Executing '%s' failed\n", test->name);
+ ++*failures;
+ } else {
+ efi_st_printc(EFI_LIGHTGREEN,
+ "Executing '%s' succeeded\n", test->name);
+ }
+ return ret;
+}
+
+/*
+ * Tear down a test.
+ *
+ * @test the test to be torn down
+ * @failures counter that will be incremented if a failure occurs
+ * @return EFI_ST_SUCCESS for success
+ */
+static int teardown(struct efi_unit_test *test, unsigned int *failures)
+{
+ int ret;
+
+ if (!test->teardown)
+ return EFI_ST_SUCCESS;
+ efi_st_printc(EFI_LIGHTBLUE, "\nTearing down '%s'\n", test->name);
+ ret = test->teardown();
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("Tearing down '%s' failed\n", test->name);
+ ++*failures;
+ } else {
+ efi_st_printc(EFI_LIGHTGREEN,
+ "Tearing down '%s' succeeded\n", test->name);
+ }
+ return ret;
+}
+
+/*
+ * Check that a test exists.
+ *
+ * @testname: name of the test
+ * @return: test, or NULL if not found
+ */
+static struct efi_unit_test *find_test(const u16 *testname)
+{
+ struct efi_unit_test *test;
+
+ for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+ test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+ if (!efi_st_strcmp_16_8(testname, test->name))
+ return test;
+ }
+ efi_st_printf("\nTest '%ps' not found\n", testname);
+ return NULL;
+}
+
+/*
+ * List all available tests.
+ */
+static void list_all_tests(void)
+{
+ struct efi_unit_test *test;
+
+ /* List all tests */
+ efi_st_printf("\nAvailable tests:\n");
+ for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+ test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+ efi_st_printf("'%s'%s\n", test->name,
+ test->on_request ? " - on request" : "");
+ }
+}
+
+/*
+ * Execute test steps of one phase.
+ *
+ * @testname name of a single selected test or NULL
+ * @phase test phase
+ * @steps steps to execute (mask with bits from EFI_ST_...)
+ * failures returns EFI_ST_SUCCESS if all test steps succeeded
+ */
+void efi_st_do_tests(const u16 *testname, unsigned int phase,
+ unsigned int steps, unsigned int *failures)
+{
+ int i = 0;
+ struct efi_unit_test *test;
+
+ for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+ test < ll_entry_end(struct efi_unit_test, efi_unit_test);
+ ++test, ++i) {
+ if (testname ?
+ efi_st_strcmp_16_8(testname, test->name) : test->on_request)
+ continue;
+ if (test->phase != phase)
+ continue;
+ if (steps & EFI_ST_SETUP)
+ setup_status[i] = setup(test, failures);
+ if (steps & EFI_ST_EXECUTE && setup_status[i] == EFI_ST_SUCCESS)
+ execute(test, failures);
+ if (steps & EFI_ST_TEARDOWN)
+ teardown(test, failures);
+ }
+}
+
+/*
+ * Execute selftest of the EFI API
+ *
+ * This is the main entry point of the EFI selftest application.
+ *
+ * All tests use a driver model and are run in three phases:
+ * setup, execute, teardown.
+ *
+ * A test may be setup and executed at boottime,
+ * it may be setup at boottime and executed at runtime,
+ * or it may be setup and executed at runtime.
+ *
+ * After executing all tests the system is reset.
+ *
+ * @image_handle: handle of the loaded EFI image
+ * @systab: EFI system table
+ */
+efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
+ struct efi_system_table *systab)
+{
+ unsigned int failures = 0;
+ const u16 *testname = NULL;
+ struct efi_loaded_image *loaded_image;
+ efi_status_t ret;
+
+ systable = systab;
+ boottime = systable->boottime;
+ runtime = systable->runtime;
+ handle = image_handle;
+ con_out = systable->con_out;
+ con_in = systable->con_in;
+
+ ret = boottime->handle_protocol(image_handle, &efi_guid_loaded_image,
+ (void **)&loaded_image);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot open loaded image protocol\n");
+ return ret;
+ }
+
+ if (loaded_image->load_options)
+ testname = (u16 *)loaded_image->load_options;
+
+ if (testname) {
+ if (!efi_st_strcmp_16_8(testname, "list") ||
+ !find_test(testname)) {
+ list_all_tests();
+ /*
+ * TODO:
+ * Once the Exit boottime service is correctly
+ * implemented we should call
+ * boottime->exit(image_handle, EFI_SUCCESS, 0, NULL);
+ * here, cf.
+ * https://lists.denx.de/pipermail/u-boot/2017-October/308720.html
+ */
+ return EFI_SUCCESS;
+ }
+ }
+
+ efi_st_printc(EFI_WHITE, "\nTesting EFI API implementation\n");
+
+ if (testname)
+ efi_st_printc(EFI_WHITE, "\nSelected test: '%ps'\n", testname);
+ else
+ efi_st_printc(EFI_WHITE, "\nNumber of tests to execute: %u\n",
+ ll_entry_count(struct efi_unit_test,
+ efi_unit_test));
+
+ /* Allocate buffer for setup results */
+ ret = boottime->allocate_pool(EFI_RUNTIME_SERVICES_DATA, sizeof(int) *
+ ll_entry_count(struct efi_unit_test,
+ efi_unit_test),
+ (void **)&setup_status);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Allocate pool failed\n");
+ return ret;
+ }
+
+ /* Execute boottime tests */
+ efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
+ &failures);
+
+ /* Execute mixed tests */
+ efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ EFI_ST_SETUP, &failures);
+
+ efi_st_exit_boot_services();
+
+ efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures);
+
+ /* Execute runtime tests */
+ efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT,
+ EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
+ &failures);
+
+ /* Give feedback */
+ efi_st_printc(EFI_WHITE, "\nSummary: %u failures\n\n", failures);
+
+ /* Reset system */
+ efi_st_printf("Preparing for reset. Press any key...\n");
+ efi_st_get_key();
+ runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
+ sizeof(reset_message), reset_message);
+ efi_st_printf("\n");
+ efi_st_error("Reset failed\n");
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/lib/efi_selftest/efi_selftest_bitblt.c b/lib/efi_selftest/efi_selftest_bitblt.c
new file mode 100644
index 00000000..fb33150c
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_bitblt.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_bitblt
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the block image transfer in the graphical output protocol.
+ * An animated submarine is shown.
+ */
+
+#include <efi_selftest.h>
+
+#define WIDTH 200
+#define HEIGHT 120
+#define DEPTH 60
+
+static const struct efi_gop_pixel BLACK = { 0, 0, 0, 0};
+static const struct efi_gop_pixel RED = { 0, 0, 255, 0};
+static const struct efi_gop_pixel ORANGE = { 0, 128, 255, 0};
+static const struct efi_gop_pixel YELLOW = { 0, 255, 255, 0};
+static const struct efi_gop_pixel GREEN = { 0, 255, 0, 0};
+static const struct efi_gop_pixel DARK_BLUE = {128, 0, 0, 0};
+static const struct efi_gop_pixel LIGHT_BLUE = {255, 192, 192, 0};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+static struct efi_gop *gop;
+static struct efi_gop_pixel *bitmap;
+static struct efi_event *event;
+static efi_uintn_t xpos;
+
+static void ellipse(efi_uintn_t x, efi_uintn_t y,
+ efi_uintn_t x0, efi_uintn_t y0,
+ efi_uintn_t x1, efi_uintn_t y1,
+ const struct efi_gop_pixel col, struct efi_gop_pixel *pix)
+{
+ efi_uintn_t xm = x0 + x1;
+ efi_uintn_t ym = y0 + y1;
+ efi_uintn_t dx = x1 - x0 + 1;
+ efi_uintn_t dy = y1 - y0 + 1;
+
+ if (dy * dy * (2 * x - xm) * (2 * x - xm) +
+ dx * dx * (2 * y - ym) * (2 * y - ym) <= dx * dx * dy * dy)
+ *pix = col;
+}
+
+static void rectangle(efi_uintn_t x, efi_uintn_t y,
+ efi_uintn_t x0, efi_uintn_t y0,
+ efi_uintn_t x1, efi_uintn_t y1,
+ const struct efi_gop_pixel col, struct efi_gop_pixel *pix)
+{
+ if (x >= x0 && y >= y0 && x <= x1 && y <= y1)
+ *pix = col;
+}
+
+/*
+ * Notification function, copies image to video.
+ * The position is incremented in each call.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ efi_uintn_t *pos = context;
+ efi_uintn_t dx, sx, width;
+
+ if (!pos)
+ return;
+
+ /* Increment position */
+ *pos += 5;
+ if (*pos >= WIDTH + gop->mode->info->width)
+ *pos = 0;
+
+ width = WIDTH;
+ dx = *pos - WIDTH;
+ sx = 0;
+ if (*pos >= gop->mode->info->width) {
+ width = WIDTH + gop->mode->info->width - *pos;
+ } else if (*pos < WIDTH) {
+ dx = 0;
+ sx = WIDTH - *pos;
+ width = *pos;
+ }
+
+ /* Copy image to video */
+ gop->blt(gop, bitmap, EFI_BLT_BUFFER_TO_VIDEO, sx, 0, dx, DEPTH,
+ width, HEIGHT, WIDTH * sizeof(struct efi_gop_pixel));
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ struct efi_gop_pixel pix;
+ efi_uintn_t x, y;
+
+ boottime = systable->boottime;
+
+ /* Create event */
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK, notify, (void *)&xpos,
+ &event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Get graphical output protocol */
+ ret = boottime->locate_protocol(&efi_gop_guid, NULL, (void **)&gop);
+ if (ret != EFI_SUCCESS) {
+ gop = NULL;
+ efi_st_printf("Graphical output protocol is not available.\n");
+ return EFI_ST_SUCCESS;
+ }
+
+ /* Prepare image of submarine */
+ ret = boottime->allocate_pool(EFI_LOADER_DATA,
+ sizeof(struct efi_gop_pixel) *
+ WIDTH * HEIGHT, (void **)&bitmap);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return EFI_ST_FAILURE;
+ }
+ for (y = 0; y < HEIGHT; ++y) {
+ for (x = 0; x < WIDTH; ++x) {
+ pix = DARK_BLUE;
+
+ /* Propeller */
+ ellipse(x, y, 35, 55, 43, 75, BLACK, &pix);
+ ellipse(x, y, 36, 56, 42, 74, LIGHT_BLUE, &pix);
+
+ ellipse(x, y, 35, 75, 43, 95, BLACK, &pix);
+ ellipse(x, y, 36, 76, 42, 94, LIGHT_BLUE, &pix);
+
+ /* Shaft */
+ rectangle(x, y, 35, 73, 100, 77, BLACK, &pix);
+
+ /* Periscope */
+ ellipse(x, y, 120, 10, 160, 50, BLACK, &pix);
+ ellipse(x, y, 121, 11, 159, 59, YELLOW, &pix);
+ ellipse(x, y, 130, 20, 150, 40, BLACK, &pix);
+ ellipse(x, y, 131, 21, 149, 49, DARK_BLUE, &pix);
+ rectangle(x, y, 135, 10, 160, 50, DARK_BLUE, &pix);
+ ellipse(x, y, 132, 10, 138, 20, BLACK, &pix);
+ ellipse(x, y, 133, 11, 139, 19, RED, &pix);
+
+ /* Rudder */
+ ellipse(x, y, 45, 40, 75, 70, BLACK, &pix);
+ ellipse(x, y, 46, 41, 74, 69, ORANGE, &pix);
+ ellipse(x, y, 45, 80, 75, 109, BLACK, &pix);
+ ellipse(x, y, 46, 81, 74, 108, RED, &pix);
+
+ /* Bridge */
+ ellipse(x, y, 100, 30, 120, 50, BLACK, &pix);
+ ellipse(x, y, 101, 31, 119, 49, GREEN, &pix);
+ ellipse(x, y, 140, 30, 160, 50, BLACK, &pix);
+ ellipse(x, y, 141, 31, 159, 49, GREEN, &pix);
+ rectangle(x, y, 110, 30, 150, 50, BLACK, &pix);
+ rectangle(x, y, 110, 31, 150, 50, GREEN, &pix);
+
+ /* Hull */
+ ellipse(x, y, 50, 40, 199, 109, BLACK, &pix);
+ ellipse(x, y, 51, 41, 198, 108, LIGHT_BLUE, &pix);
+
+ /* Port holes */
+ ellipse(x, y, 79, 57, 109, 82, BLACK, &pix);
+ ellipse(x, y, 80, 58, 108, 81, LIGHT_BLUE, &pix);
+ ellipse(x, y, 83, 61, 105, 78, BLACK, &pix);
+ ellipse(x, y, 84, 62, 104, 77, YELLOW, &pix);
+ /*
+ * This port hole is created by copying
+ * ellipse(x, y, 119, 57, 149, 82, BLACK, &pix);
+ * ellipse(x, y, 120, 58, 148, 81, LIGHT_BLUE, &pix);
+ * ellipse(x, y, 123, 61, 145, 78, BLACK, &pix);
+ * ellipse(x, y, 124, 62, 144, 77, YELLOW, &pix);
+ */
+ ellipse(x, y, 159, 57, 189, 82, BLACK, &pix);
+ ellipse(x, y, 160, 58, 188, 81, LIGHT_BLUE, &pix);
+ ellipse(x, y, 163, 61, 185, 78, BLACK, &pix);
+ ellipse(x, y, 164, 62, 184, 77, YELLOW, &pix);
+
+ bitmap[WIDTH * y + x] = pix;
+ }
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ if (bitmap) {
+ ret = boottime->free_pool(bitmap);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (event) {
+ ret = boottime->close_event(event);
+ event = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ u32 max_mode;
+ efi_status_t ret;
+ struct efi_gop_mode_info *info;
+
+ if (!gop)
+ return EFI_ST_SUCCESS;
+
+ if (!gop->mode) {
+ efi_st_error("EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE missing\n");
+ return EFI_ST_FAILURE;
+ }
+ info = gop->mode->info;
+ max_mode = gop->mode->max_mode;
+ if (!max_mode) {
+ efi_st_error("No graphical mode available\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Fill background */
+ ret = gop->blt(gop, bitmap, EFI_BLT_VIDEO_FILL, 0, 0, 0, 0,
+ info->width, info->height, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("EFI_BLT_VIDEO_FILL failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Copy image to video */
+ ret = gop->blt(gop, bitmap, EFI_BLT_BUFFER_TO_VIDEO, 0, 0, 0, DEPTH,
+ WIDTH, HEIGHT, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("EFI_BLT_BUFFER_TO_VIDEO failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Copy left port hole */
+ ret = gop->blt(gop, bitmap, EFI_BLT_VIDEO_TO_VIDEO,
+ 79, 57 + DEPTH, 119, 57 + DEPTH,
+ 31, 26, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("EFI_BLT_VIDEO_TO_VIDEO failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Copy port holes back to buffer */
+ ret = gop->blt(gop, bitmap, EFI_BLT_VIDEO_TO_BLT_BUFFER,
+ 94, 57 + DEPTH, 94, 57,
+ 90, 26, WIDTH * sizeof(struct efi_gop_pixel));
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("EFI_BLT_VIDEO_TO_BLT_BUFFER failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Set 250ms timer */
+ xpos = WIDTH;
+ ret = boottime->set_timer(event, EFI_TIMER_PERIODIC, 250000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+
+ con_out->set_cursor_position(con_out, 0, 0);
+ con_out->set_attribute(con_out, EFI_WHITE | EFI_BACKGROUND_BLUE);
+ efi_st_printf("The submarine should have three yellow port holes.\n");
+ efi_st_printf("Press any key to continue");
+ efi_st_get_key();
+ con_out->set_attribute(con_out, EFI_LIGHTGRAY);
+ efi_st_printf("\n");
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(bitblt) = {
+ .name = "block image transfer",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+ .on_request = true,
+};
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
new file mode 100644
index 00000000..644c5ade
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_block
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the driver for block IO devices.
+ * A disk image is created in memory.
+ * A handle is created for the new block IO device.
+ * The block I/O protocol is installed on the handle.
+ * ConnectController is used to setup partitions and to install the simple
+ * file protocol.
+ * A known file is read from the file system and verified.
+ */
+
+#include <efi_selftest.h>
+#include "efi_selftest_disk_image.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static struct efi_boot_services *boottime;
+
+static const efi_guid_t block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID;
+static const efi_guid_t guid_simple_file_system_protocol =
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID;
+static efi_guid_t guid_vendor =
+ EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+ 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8);
+
+static struct efi_device_path *dp;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed disk image */
+struct compressed_disk_image {
+ size_t length;
+ struct line lines[];
+};
+
+static const struct compressed_disk_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed disk image */
+static u8 *image;
+
+/*
+ * Reset service of the block IO protocol.
+ *
+ * @this block IO protocol
+ * @return status code
+ */
+static efi_status_t EFIAPI reset(
+ struct efi_block_io *this,
+ char extended_verification)
+{
+ return EFI_SUCCESS;
+}
+
+/*
+ * Read service of the block IO protocol.
+ *
+ * @this block IO protocol
+ * @media_id media id
+ * @lba start of the read in logical blocks
+ * @buffer_size number of bytes to read
+ * @buffer target buffer
+ * @return status code
+ */
+static efi_status_t EFIAPI read_blocks(
+ struct efi_block_io *this, u32 media_id, u64 lba,
+ efi_uintn_t buffer_size, void *buffer)
+{
+ u8 *start;
+
+ if ((lba << LB_BLOCK_SIZE) + buffer_size > img.length)
+ return EFI_INVALID_PARAMETER;
+ start = image + (lba << LB_BLOCK_SIZE);
+
+ boottime->copy_mem(buffer, start, buffer_size);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * Write service of the block IO protocol.
+ *
+ * @this block IO protocol
+ * @media_id media id
+ * @lba start of the write in logical blocks
+ * @buffer_size number of bytes to read
+ * @buffer source buffer
+ * @return status code
+ */
+static efi_status_t EFIAPI write_blocks(
+ struct efi_block_io *this, u32 media_id, u64 lba,
+ efi_uintn_t buffer_size, void *buffer)
+{
+ u8 *start;
+
+ if ((lba << LB_BLOCK_SIZE) + buffer_size > img.length)
+ return EFI_INVALID_PARAMETER;
+ start = image + (lba << LB_BLOCK_SIZE);
+
+ boottime->copy_mem(start, buffer, buffer_size);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * Flush service of the block IO protocol.
+ *
+ * @this block IO protocol
+ * @return status code
+ */
+static efi_status_t EFIAPI flush_blocks(struct efi_block_io *this)
+{
+ return EFI_SUCCESS;
+}
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ return ret;
+}
+
+static struct efi_block_io_media media;
+
+static struct efi_block_io block_io = {
+ .media = &media,
+ .reset = reset,
+ .read_blocks = read_blocks,
+ .write_blocks = write_blocks,
+ .flush_blocks = flush_blocks,
+};
+
+/* Handle for the block IO device */
+static efi_handle_t disk_handle;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ struct efi_device_path_vendor vendor_node;
+ struct efi_device_path end_node;
+
+ boottime = systable->boottime;
+
+ decompress(&image);
+
+ block_io.media->block_size = 1 << LB_BLOCK_SIZE;
+ block_io.media->last_block = img.length >> LB_BLOCK_SIZE;
+
+ ret = boottime->install_protocol_interface(
+ &disk_handle, &block_io_protocol_guid,
+ EFI_NATIVE_INTERFACE, &block_io);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install block I/O protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA,
+ sizeof(struct efi_device_path_vendor) +
+ sizeof(struct efi_device_path),
+ (void **)&dp);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return EFI_ST_FAILURE;
+ }
+ vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+ vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
+
+ boottime->copy_mem(&vendor_node.guid, &guid_vendor,
+ sizeof(efi_guid_t));
+ boottime->copy_mem(dp, &vendor_node,
+ sizeof(struct efi_device_path_vendor));
+ end_node.type = DEVICE_PATH_TYPE_END;
+ end_node.sub_type = DEVICE_PATH_SUB_TYPE_END;
+ end_node.length = sizeof(struct efi_device_path);
+
+ boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor),
+ &end_node, sizeof(struct efi_device_path));
+ ret = boottime->install_protocol_interface(&disk_handle,
+ &guid_device_path,
+ EFI_NATIVE_INTERFACE,
+ dp);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t r = EFI_ST_SUCCESS;
+
+ if (disk_handle) {
+ r = boottime->uninstall_protocol_interface(disk_handle,
+ &guid_device_path,
+ dp);
+ if (r != EFI_SUCCESS) {
+ efi_st_error("Uninstall device path failed\n");
+ return EFI_ST_FAILURE;
+ }
+ r = boottime->uninstall_protocol_interface(
+ disk_handle, &block_io_protocol_guid,
+ &block_io);
+ if (r != EFI_SUCCESS) {
+ efi_st_todo(
+ "Failed to uninstall block I/O protocol\n");
+ return EFI_ST_SUCCESS;
+ }
+ }
+
+ if (image) {
+ r = boottime->free_pool(image);
+ if (r != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return r;
+}
+
+/*
+ * Get length of device path without end tag.
+ *
+ * @dp device path
+ * @return length of device path in bytes
+ */
+static efi_uintn_t dp_size(struct efi_device_path *dp)
+{
+ struct efi_device_path *pos = dp;
+
+ while (pos->type != DEVICE_PATH_TYPE_END)
+ pos = (struct efi_device_path *)((char *)pos + pos->length);
+ return (char *)pos - (char *)dp;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t no_handles, i, len;
+ efi_handle_t *handles;
+ efi_handle_t handle_partition = NULL;
+ struct efi_device_path *dp_partition;
+ struct efi_simple_file_system_protocol *file_system;
+ struct efi_file_handle *root, *file;
+ struct {
+ struct efi_file_system_info info;
+ u16 label[12];
+ } system_info;
+ efi_uintn_t buf_size;
+ char buf[16] __aligned(ARCH_DMA_MINALIGN);
+ u64 pos;
+
+ /* Connect controller to virtual disk */
+ ret = boottime->connect_controller(disk_handle, NULL, NULL, 1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to connect controller\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Get the handle for the partition */
+ ret = boottime->locate_handle_buffer(
+ BY_PROTOCOL, &guid_device_path, NULL,
+ &no_handles, &handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to locate handles\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dp_size(dp);
+ for (i = 0; i < no_handles; ++i) {
+ ret = boottime->open_protocol(handles[i], &guid_device_path,
+ (void **)&dp_partition,
+ NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open device path protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ if (len >= dp_size(dp_partition))
+ continue;
+ if (memcmp(dp, dp_partition, len))
+ continue;
+ handle_partition = handles[i];
+ break;
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to free pool memory\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!handle_partition) {
+ efi_st_error("Partition handle not found\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Open the simple file system protocol */
+ ret = boottime->open_protocol(handle_partition,
+ &guid_simple_file_system_protocol,
+ (void **)&file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open simple file system protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Open volume */
+ ret = file_system->open_volume(file_system, &root);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open volume\n");
+ return EFI_ST_FAILURE;
+ }
+ buf_size = sizeof(system_info);
+ ret = root->getinfo(root, &guid_file_system_info, &buf_size,
+ &system_info);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to get file system info\n");
+ return EFI_ST_FAILURE;
+ }
+ if (system_info.info.block_size != 512) {
+ efi_st_error("Wrong block size %u, expected 512\n",
+ system_info.info.block_size);
+ return EFI_ST_FAILURE;
+ }
+ if (efi_st_strcmp_16_8(system_info.info.volume_label, "U-BOOT TEST")) {
+ efi_st_todo(
+ "Wrong volume label '%ps', expected 'U-BOOT TEST'\n",
+ system_info.info.volume_label);
+ }
+
+ /* Read file */
+ ret = root->open(root, &file, L"hello.txt", EFI_FILE_MODE_READ,
+ 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open file\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = file->setpos(file, 1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetPosition failed\n");
+ return EFI_ST_FAILURE;
+ }
+ buf_size = sizeof(buf) - 1;
+ ret = file->read(file, &buf_size, buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to read file\n");
+ return EFI_ST_FAILURE;
+ }
+ if (buf_size != 12) {
+ efi_st_error("Wrong number of bytes read: %u\n",
+ (unsigned int)buf_size);
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(buf, "ello world!", 11)) {
+ efi_st_error("Unexpected file content\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = file->getpos(file, &pos);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetPosition failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (pos != 13) {
+ efi_st_error("GetPosition returned %u, expected 13\n",
+ (unsigned int)pos);
+ return EFI_ST_FAILURE;
+ }
+ ret = file->close(file);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close file\n");
+ return EFI_ST_FAILURE;
+ }
+
+#ifdef CONFIG_FAT_WRITE
+ /* Write file */
+ ret = root->open(root, &file, L"u-boot.txt", EFI_FILE_MODE_READ |
+ EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open file\n");
+ return EFI_ST_FAILURE;
+ }
+ buf_size = 7;
+ boottime->set_mem(buf, sizeof(buf), 0);
+ boottime->copy_mem(buf, "U-Boot", buf_size);
+ ret = file->write(file, &buf_size, buf);
+ if (ret != EFI_SUCCESS || buf_size != 7) {
+ efi_st_error("Failed to write file\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = file->getpos(file, &pos);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetPosition failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (pos != 7) {
+ efi_st_error("GetPosition returned %u, expected 7\n",
+ (unsigned int)pos);
+ return EFI_ST_FAILURE;
+ }
+ ret = file->close(file);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close file\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Verify file */
+ boottime->set_mem(buf, sizeof(buf), 0);
+ ret = root->open(root, &file, L"u-boot.txt", EFI_FILE_MODE_READ,
+ 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to open file\n");
+ return EFI_ST_FAILURE;
+ }
+ buf_size = sizeof(buf) - 1;
+ ret = file->read(file, &buf_size, buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to read file\n");
+ return EFI_ST_FAILURE;
+ }
+ if (buf_size != 7) {
+ efi_st_error("Wrong number of bytes read: %u\n",
+ (unsigned int)buf_size);
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(buf, "U-Boot", 7)) {
+ efi_st_error("Unexpected file content %s\n", buf);
+ return EFI_ST_FAILURE;
+ }
+ ret = file->close(file);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close file\n");
+ return EFI_ST_FAILURE;
+ }
+#else
+ efi_st_todo("CONFIG_FAT_WRITE is not set\n");
+#endif /* CONFIG_FAT_WRITE */
+
+ /* Close volume */
+ ret = root->close(root);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close volume\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(blkdev) = {
+ .name = "block device",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_config_table.c b/lib/efi_selftest/efi_selftest_config_table.c
new file mode 100644
index 00000000..2bf12b5b
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_config_table.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_config_tables
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the following service:
+ * InstallConfigurationTable.
+ */
+
+#include <efi_selftest.h>
+#include <u-boot/crc.h>
+
+static const struct efi_system_table *sys_table;
+static struct efi_boot_services *boottime;
+
+static efi_guid_t table_guid =
+ EFI_GUID(0xff1c3f9e, 0x795b, 0x1529, 0xf1, 0x55,
+ 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75);
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ unsigned int *count = context;
+
+ if (count)
+ ++*count;
+}
+
+/*
+ * Check CRC32 of a table.
+ */
+static int check_table(const void *table)
+{
+ efi_status_t ret;
+ u32 crc32, res;
+ /* Casting from constant to not constant */
+ struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
+
+ crc32 = hdr->crc32;
+ /*
+ * Setting the CRC32 of the 'const' table to zero is easier than
+ * copying
+ */
+ hdr->crc32 = 0;
+ ret = boottime->calculate_crc32(table, hdr->headersize, &res);
+ /* Reset table CRC32 so it stays constant */
+ hdr->crc32 = crc32;
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("CalculateCrc32 failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (res != crc32) {
+ efi_st_error("Incorrect CRC32\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ sys_table = systable;
+ boottime = systable->boottime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * A table is installed, updated, removed. The table entry and the
+ * triggering of events is checked.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ unsigned int counter = 0;
+ struct efi_event *event;
+ void *table;
+ const unsigned int tables[2];
+ efi_uintn_t i;
+ efi_uintn_t tabcnt;
+ efi_uintn_t table_count = sys_table->nr_tables;
+
+ ret = boottime->create_event_ex(0, TPL_NOTIFY,
+ notify, (void *)&counter,
+ &table_guid, &event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to create event\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Try to delete non-existent table */
+ ret = boottime->install_configuration_table(&table_guid, NULL);
+ if (ret != EFI_NOT_FOUND) {
+ efi_st_error("Failed to detect missing table\n");
+ return EFI_ST_FAILURE;
+ }
+ if (counter) {
+ efi_st_error("Notification function was called.\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check if the event was signaled */
+ ret = boottime->check_event(event);
+ if (ret == EFI_SUCCESS) {
+ efi_st_error("Event was signaled on EFI_NOT_FOUND\n");
+ return EFI_ST_FAILURE;
+ }
+ if (counter != 1) {
+ efi_st_error("Notification function was not called.\n");
+ return EFI_ST_FAILURE;
+ }
+ if (table_count != sys_table->nr_tables) {
+ efi_st_error("Incorrect table count %u, expected %u\n",
+ (unsigned int)sys_table->nr_tables,
+ (unsigned int)table_count);
+ return EFI_ST_FAILURE;
+ }
+
+ /* Install table */
+ ret = boottime->install_configuration_table(&table_guid,
+ (void *)&tables[0]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install table\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check signaled state */
+ ret = boottime->check_event(event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Event was not signaled on insert\n");
+ return EFI_ST_FAILURE;
+ }
+ if (++table_count != sys_table->nr_tables) {
+ efi_st_error("Incorrect table count %u, expected %u\n",
+ (unsigned int)sys_table->nr_tables,
+ (unsigned int)table_count);
+ return EFI_ST_FAILURE;
+ }
+ table = NULL;
+ for (i = 0; i < sys_table->nr_tables; ++i) {
+ if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+ sizeof(efi_guid_t)))
+ table = sys_table->tables[i].table;
+ }
+ if (!table) {
+ efi_st_error("Installed table not found\n");
+ return EFI_ST_FAILURE;
+ }
+ if (table != &tables[0]) {
+ efi_st_error("Incorrect table address\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(sys_table) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking system table\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Update table */
+ ret = boottime->install_configuration_table(&table_guid,
+ (void *)&tables[1]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to update table\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check signaled state */
+ ret = boottime->check_event(event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Event was not signaled on update\n");
+ return EFI_ST_FAILURE;
+ }
+ if (table_count != sys_table->nr_tables) {
+ efi_st_error("Incorrect table count %u, expected %u\n",
+ (unsigned int)sys_table->nr_tables,
+ (unsigned int)table_count);
+ return EFI_ST_FAILURE;
+ }
+ table = NULL;
+ tabcnt = 0;
+ for (i = 0; i < sys_table->nr_tables; ++i) {
+ if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+ sizeof(efi_guid_t))) {
+ table = sys_table->tables[i].table;
+ ++tabcnt;
+ }
+ }
+ if (!table) {
+ efi_st_error("Installed table not found\n");
+ return EFI_ST_FAILURE;
+ }
+ if (tabcnt > 1) {
+ efi_st_error("Duplicate table GUID\n");
+ return EFI_ST_FAILURE;
+ }
+ if (table != &tables[1]) {
+ efi_st_error("Incorrect table address\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(sys_table) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking system table\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Delete table */
+ ret = boottime->install_configuration_table(&table_guid, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to delete table\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check signaled state */
+ ret = boottime->check_event(event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Event was not signaled on delete\n");
+ return EFI_ST_FAILURE;
+ }
+ if (--table_count != sys_table->nr_tables) {
+ efi_st_error("Incorrect table count %u, expected %u\n",
+ (unsigned int)sys_table->nr_tables,
+ (unsigned int)table_count);
+ return EFI_ST_FAILURE;
+ }
+ table = NULL;
+ for (i = 0; i < sys_table->nr_tables; ++i) {
+ if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+ sizeof(efi_guid_t))) {
+ table = sys_table->tables[i].table;
+ }
+ }
+ if (table) {
+ efi_st_error("Wrong table deleted\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->close_event(event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(sys_table) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking system table\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(configtables) = {
+ .name = "configuration tables",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c
new file mode 100644
index 00000000..42f51b65
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_console.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+struct efi_simple_text_output_protocol *con_out;
+struct efi_simple_text_input_protocol *con_in;
+
+/*
+ * Print a MAC address to an u16 string
+ *
+ * @pointer: mac address
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void mac(void *pointer, u16 **buf)
+{
+ int i, j;
+ u16 c;
+ u8 *p = (u8 *)pointer;
+ u8 byte;
+ u16 *pos = *buf;
+
+ for (i = 0; i < ARP_HLEN; ++i) {
+ if (i)
+ *pos++ = ':';
+ byte = p[i];
+ for (j = 4; j >= 0; j -= 4) {
+ c = (byte >> j) & 0x0f;
+ c += '0';
+ if (c > '9')
+ c += 'a' - '9' - 1;
+ *pos++ = c;
+ }
+ }
+ *pos = 0;
+ *buf = pos;
+}
+
+/*
+ * Print a pointer to an u16 string
+ *
+ * @pointer: pointer
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void pointer(void *pointer, u16 **buf)
+{
+ int i;
+ u16 c;
+ uintptr_t p = (uintptr_t)pointer;
+ u16 *pos = *buf;
+
+ for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
+ c = (p >> i) & 0x0f;
+ c += '0';
+ if (c > '9')
+ c += 'a' - '9' - 1;
+ *pos++ = c;
+ }
+ *pos = 0;
+ *buf = pos;
+}
+
+/*
+ * Print an unsigned 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @prec: minimum number of digits to display
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void uint2dec(u32 value, int prec, u16 **buf)
+{
+ u16 *pos = *buf;
+ int i;
+ u16 c;
+ u64 f;
+
+ /*
+ * Increment by .5 and multiply with
+ * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
+ * to move the first digit to bit 60-63.
+ */
+ f = 0x225C17D0;
+ f += (0x9B5A52DULL * value) >> 28;
+ f += 0x44B82FA0ULL * value;
+
+ for (i = 0; i < 10; ++i) {
+ /* Write current digit */
+ c = f >> 60;
+ if (c || pos != *buf || 10 - i <= prec)
+ *pos++ = c + '0';
+ /* Eliminate current digit */
+ f &= 0xfffffffffffffff;
+ /* Get next digit */
+ f *= 0xaULL;
+ }
+ if (pos == *buf)
+ *pos++ = '0';
+ *pos = 0;
+ *buf = pos;
+}
+
+/*
+ * Print a signed 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @prec: minimum number of digits to display
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void int2dec(s32 value, int prec, u16 **buf)
+{
+ u32 u;
+ u16 *pos = *buf;
+
+ if (value < 0) {
+ *pos++ = '-';
+ u = -value;
+ } else {
+ u = value;
+ }
+ uint2dec(u, prec, &pos);
+ *buf = pos;
+}
+
+/*
+ * Print a colored formatted string to the EFI console
+ *
+ * @color color, see constants in efi_api.h, use -1 for no color
+ * @fmt format string
+ * @... optional arguments
+ */
+void efi_st_printc(int color, const char *fmt, ...)
+{
+ va_list args;
+ u16 buf[160];
+ const char *c;
+ u16 *pos = buf;
+ const char *s;
+ u16 *u;
+ int prec;
+
+ va_start(args, fmt);
+
+ if (color >= 0)
+ con_out->set_attribute(con_out, (unsigned long)color);
+ c = fmt;
+ for (; *c; ++c) {
+ switch (*c) {
+ case '\\':
+ ++c;
+ switch (*c) {
+ case '\0':
+ --c;
+ break;
+ case 'n':
+ *pos++ = '\n';
+ break;
+ case 'r':
+ *pos++ = '\r';
+ break;
+ case 't':
+ *pos++ = '\t';
+ break;
+ default:
+ *pos++ = *c;
+ }
+ break;
+ case '%':
+ ++c;
+ /* Parse precision */
+ if (*c == '.') {
+ ++c;
+ prec = *c - '0';
+ ++c;
+ } else {
+ prec = 0;
+ }
+ switch (*c) {
+ case '\0':
+ --c;
+ break;
+ case 'd':
+ int2dec(va_arg(args, s32), prec, &pos);
+ break;
+ case 'p':
+ ++c;
+ switch (*c) {
+ /* MAC address */
+ case 'm':
+ mac(va_arg(args, void*), &pos);
+ break;
+
+ /* u16 string */
+ case 's':
+ u = va_arg(args, u16*);
+ if (pos > buf) {
+ *pos = 0;
+ con_out->output_string(con_out,
+ buf);
+ }
+ con_out->output_string(con_out, u);
+ pos = buf;
+ break;
+ default:
+ --c;
+ pointer(va_arg(args, void*), &pos);
+ }
+ break;
+ case 's':
+ s = va_arg(args, const char *);
+ for (; *s; ++s)
+ *pos++ = *s;
+ break;
+ case 'u':
+ uint2dec(va_arg(args, u32), prec, &pos);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ *pos++ = *c;
+ }
+ }
+ va_end(args);
+ *pos = 0;
+ con_out->output_string(con_out, buf);
+ if (color >= 0)
+ con_out->set_attribute(con_out, EFI_LIGHTGRAY);
+}
+
+/*
+ * Reads an Unicode character from the input device.
+ *
+ * @return: Unicode character
+ */
+u16 efi_st_get_key(void)
+{
+ struct efi_input_key input_key;
+ efi_status_t ret;
+
+ /* Wait for next key */
+ do {
+ ret = con_in->read_key_stroke(con_in, &input_key);
+ } while (ret == EFI_NOT_READY);
+ return input_key.unicode_char;
+}
diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c
new file mode 100644
index 00000000..38720bb6
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_controllers.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_controllers
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * ConnectController, DisconnectController,
+ * InstallProtocol, ReinstallProtocol, UninstallProtocol,
+ * OpenProtocol, CloseProtcol, OpenProtocolInformation
+ */
+
+#include <efi_selftest.h>
+
+#define NUMBER_OF_CHILD_CONTROLLERS 4
+
+static int interface1 = 1;
+static int interface2 = 2;
+static struct efi_boot_services *boottime;
+const efi_guid_t guid_driver_binding_protocol =
+ EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static efi_guid_t guid_controller =
+ EFI_GUID(0xe6ab1d96, 0x6bff, 0xdb42,
+ 0xaa, 0x05, 0xc8, 0x1f, 0x7f, 0x45, 0x26, 0x34);
+static efi_guid_t guid_child_controller =
+ EFI_GUID(0x1d41f6f5, 0x2c41, 0xddfb,
+ 0xe2, 0x9b, 0xb8, 0x0e, 0x2e, 0xe8, 0x3a, 0x85);
+static efi_handle_t handle_controller;
+static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS];
+static efi_handle_t handle_driver;
+
+/*
+ * Count child controllers
+ *
+ * @handle handle on which child controllers are installed
+ * @protocol protocol for which the child controllers were installed
+ * @count number of child controllers
+ * @return status code
+ */
+static efi_status_t count_child_controllers(efi_handle_t handle,
+ efi_guid_t *protocol,
+ efi_uintn_t *count)
+{
+ efi_status_t ret;
+ efi_uintn_t entry_count;
+ struct efi_open_protocol_info_entry *entry_buffer;
+
+ *count = 0;
+ ret = boottime->open_protocol_information(handle, protocol,
+ &entry_buffer, &entry_count);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (!entry_count)
+ return EFI_SUCCESS;
+ while (entry_count) {
+ if (entry_buffer[--entry_count].attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
+ ++*count;
+ }
+ ret = boottime->free_pool(entry_buffer);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("Cannot free buffer\n");
+ return ret;
+}
+
+/*
+ * Check if the driver supports the controller.
+ *
+ * @this driver binding protocol
+ * @controller_handle handle of the controller
+ * @remaining_device_path path specifying the child controller
+ * @return status code
+ */
+static efi_status_t EFIAPI supported(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ struct efi_device_path *remaining_device_path)
+{
+ efi_status_t ret;
+ void *interface;
+
+ ret = boottime->open_protocol(
+ controller_handle, &guid_controller,
+ &interface, handle_driver,
+ controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ switch (ret) {
+ case EFI_ACCESS_DENIED:
+ case EFI_ALREADY_STARTED:
+ return ret;
+ case EFI_SUCCESS:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ ret = boottime->close_protocol(
+ controller_handle, &guid_controller,
+ handle_driver, controller_handle);
+ if (ret != EFI_SUCCESS)
+ ret = EFI_UNSUPPORTED;
+ return ret;
+}
+
+/*
+ * Create child controllers and attach driver.
+ *
+ * @this driver binding protocol
+ * @controller_handle handle of the controller
+ * @remaining_device_path path specifying the child controller
+ * @return status code
+ */
+static efi_status_t EFIAPI start(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ struct efi_device_path *remaining_device_path)
+{
+ size_t i;
+ efi_status_t ret;
+ void *interface;
+
+ /* Attach driver to controller */
+ ret = boottime->open_protocol(
+ controller_handle, &guid_controller,
+ &interface, handle_driver,
+ controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ switch (ret) {
+ case EFI_ACCESS_DENIED:
+ case EFI_ALREADY_STARTED:
+ return ret;
+ case EFI_SUCCESS:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ /* Create child controllers */
+ for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
+ /* Creating a new handle for the child controller */
+ handle_child_controller[i] = 0;
+ ret = boottime->install_protocol_interface(
+ &handle_child_controller[i], &guid_child_controller,
+ EFI_NATIVE_INTERFACE, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol(
+ controller_handle, &guid_controller,
+ &interface, handle_child_controller[i],
+ handle_child_controller[i],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Remove a single child controller from the parent controller.
+ *
+ * @controller_handle parent controller
+ * @child_handle child controller
+ * @return status code
+ */
+static efi_status_t disconnect_child(efi_handle_t controller_handle,
+ efi_handle_t child_handle)
+{
+ efi_status_t ret;
+
+ ret = boottime->close_protocol(
+ controller_handle, &guid_controller,
+ child_handle, child_handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot close protocol\n");
+ return ret;
+ }
+ ret = boottime->uninstall_protocol_interface(
+ child_handle, &guid_child_controller, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot uninstall protocol interface\n");
+ return ret;
+ }
+ return ret;
+}
+
+/*
+ * Remove child controllers and disconnect the controller.
+ *
+ * @this driver binding protocol
+ * @controller_handle handle of the controller
+ * @number_of_children number of child controllers to remove
+ * @child_handle_buffer handles of the child controllers to remove
+ * @return status code
+ */
+static efi_status_t EFIAPI stop(
+ struct efi_driver_binding_protocol *this,
+ efi_handle_t controller_handle,
+ size_t number_of_children,
+ efi_handle_t *child_handle_buffer)
+{
+ efi_status_t ret;
+ efi_uintn_t count;
+ struct efi_open_protocol_info_entry *entry_buffer;
+
+ /* Destroy provided child controllers */
+ if (number_of_children) {
+ efi_uintn_t i;
+
+ for (i = 0; i < number_of_children; ++i) {
+ ret = disconnect_child(controller_handle,
+ child_handle_buffer[i]);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ return EFI_SUCCESS;
+ }
+
+ /* Destroy all children */
+ ret = boottime->open_protocol_information(
+ controller_handle, &guid_controller,
+ &entry_buffer, &count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocolInformation failed\n");
+ return ret;
+ }
+ while (count) {
+ if (entry_buffer[--count].attributes &
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ ret = disconnect_child(
+ controller_handle,
+ entry_buffer[count].agent_handle);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ }
+ ret = boottime->free_pool(entry_buffer);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("Cannot free buffer\n");
+
+ /* Detach driver from controller */
+ ret = boottime->close_protocol(
+ controller_handle, &guid_controller,
+ handle_driver, controller_handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot close protocol\n");
+ return ret;
+ }
+ return EFI_SUCCESS;
+}
+
+/* Driver binding protocol interface */
+static struct efi_driver_binding_protocol binding_interface = {
+ supported,
+ start,
+ stop,
+ 0xffffffff,
+ NULL,
+ NULL,
+ };
+
+/*
+ * Setup unit test.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ /* Create controller handle */
+ ret = boottime->install_protocol_interface(
+ &handle_controller, &guid_controller,
+ EFI_NATIVE_INTERFACE, &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Create driver handle */
+ ret = boottime->install_protocol_interface(
+ &handle_driver, &guid_driver_binding_protocol,
+ EFI_NATIVE_INTERFACE, &binding_interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * The number of child controllers is checked after each of the following
+ * actions:
+ *
+ * Connect a controller to a driver.
+ * Disconnect and destroy a child controller.
+ * Disconnect and destroy the remaining child controllers.
+ *
+ * Connect a controller to a driver.
+ * Reinstall the driver protocol on the controller.
+ * Uninstall the driver protocol from the controller.
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t count;
+
+ /* Connect controller to driver */
+ ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to connect controller\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
+ efi_st_error("Number of children %u != %u\n",
+ (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
+ }
+ /* Destroy second child controller */
+ ret = boottime->disconnect_controller(handle_controller,
+ handle_driver,
+ handle_child_controller[1]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to disconnect child controller\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
+ efi_st_error("Destroying single child controller failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Destroy remaining child controllers and disconnect controller */
+ ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to disconnect controller\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret != EFI_SUCCESS || count) {
+ efi_st_error("Destroying child controllers failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Connect controller to driver */
+ ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to connect controller\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
+ efi_st_error("Number of children %u != %u\n",
+ (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
+ }
+ /* Try to uninstall controller protocol using the wrong interface */
+ ret = boottime->uninstall_protocol_interface(handle_controller,
+ &guid_controller,
+ &interface2);
+ if (ret == EFI_SUCCESS) {
+ efi_st_error(
+ "Interface not checked when uninstalling protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Reinstall controller protocol */
+ ret = boottime->reinstall_protocol_interface(handle_controller,
+ &guid_controller,
+ &interface1,
+ &interface2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to reinstall protocols\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
+ efi_st_error("Number of children %u != %u\n",
+ (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
+ }
+ /* Uninstall controller protocol */
+ ret = boottime->uninstall_protocol_interface(handle_controller,
+ &guid_controller,
+ &interface2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to uninstall protocols\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Check number of child controllers */
+ ret = count_child_controllers(handle_controller, &guid_controller,
+ &count);
+ if (ret == EFI_SUCCESS)
+ efi_st_error("Uninstall failed\n");
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(controllers) = {
+ .name = "controllers",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_crc32.c b/lib/efi_selftest/efi_selftest_crc32.c
new file mode 100644
index 00000000..19153c75
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_crc32.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_crc32
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the CalculateCrc32 bootservice and checks the
+ * headers of the system table, the boot services table, and the runtime
+ * services table before and after ExitBootServices().
+ */
+
+#include <efi_selftest.h>
+#include <u-boot/crc.h>
+
+const struct efi_system_table *st;
+efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size,
+ u32 *crc32);
+
+static int check_table(const void *table)
+{
+ efi_status_t ret;
+ u32 crc32, res;
+ /* Casting from constant to not constant */
+ struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
+
+ if (!hdr->signature) {
+ efi_st_error("Missing header signature\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!hdr->revision) {
+ efi_st_error("Missing header revision\n");
+ return EFI_ST_FAILURE;
+ }
+ if (hdr->headersize <= sizeof(struct efi_table_hdr)) {
+ efi_st_error("Incorrect headersize value\n");
+ return EFI_ST_FAILURE;
+ }
+ if (hdr->reserved) {
+ efi_st_error("Reserved header field is not zero\n");
+ return EFI_ST_FAILURE;
+ }
+
+ crc32 = hdr->crc32;
+ /*
+ * Setting the crc32 of the 'const' table to zero is easier than
+ * copying
+ */
+ hdr->crc32 = 0;
+ ret = bs_crc32(table, hdr->headersize, &res);
+ /* Reset table crc32 so it stays constant */
+ hdr->crc32 = crc32;
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("CalculateCrc32 failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (res != crc32) {
+ efi_st_error("Incorrect CRC32\n");
+ // return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Check that CalculateCrc32 is working correctly.
+ * Check tables before ExitBootServices().
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ u32 res;
+
+ st = systable;
+ bs_crc32 = systable->boottime->calculate_crc32;
+
+ /* Check that CalculateCrc32 is working */
+ ret = bs_crc32("U-Boot", 6, &res);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("CalculateCrc32 failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (res != 0x134b0db4) {
+ efi_st_error("Incorrect CRC32\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Check tables before ExitBootServices() */
+ if (check_table(st) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking system table\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(st->boottime) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking boottime table\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(st->runtime) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking runtime table\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test
+ *
+ * Check tables after ExitBootServices()
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ if (check_table(st) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking system table\n");
+ return EFI_ST_FAILURE;
+ }
+ if (check_table(st->runtime) != EFI_ST_SUCCESS) {
+ efi_st_error("Checking runtime table\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * We cannot call SetVirtualAddressMap() and recheck the runtime
+ * table afterwards because this would invalidate the addresses of the
+ * unit tests.
+ */
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(crc32) = {
+ .name = "crc32",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c
new file mode 100644
index 00000000..4ce3fad8
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_devicepath.c
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_devicepath
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * DevicePathToText
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+
+static efi_handle_t handle1;
+static efi_handle_t handle2;
+static efi_handle_t handle3;
+
+struct interface {
+ void (EFIAPI * inc)(void);
+} interface;
+
+static efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID;
+
+static efi_guid_t guid_device_path_to_text_protocol =
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+
+static efi_guid_t guid_protocol =
+ EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+ 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d);
+
+static efi_guid_t guid_vendor1 =
+ EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+ 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1);
+
+static efi_guid_t guid_vendor2 =
+ EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+ 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2);
+
+static efi_guid_t guid_vendor3 =
+ EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+ 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3);
+
+static u8 *dp1;
+static u8 *dp2;
+static u8 *dp3;
+
+struct efi_device_path_to_text_protocol *device_path_to_text;
+
+/*
+ * Setup unit test.
+ *
+ * Create three handles. Install a new protocol on two of them and
+ * provide device paths.
+ *
+ * handle1
+ * guid interface
+ * handle2
+ * guid interface
+ * handle3
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ struct efi_device_path_vendor vendor_node;
+ struct efi_device_path end_node;
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->locate_protocol(&guid_device_path_to_text_protocol,
+ NULL, (void **)&device_path_to_text);
+ if (ret != EFI_SUCCESS) {
+ device_path_to_text = NULL;
+ efi_st_error(
+ "Device path to text protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA,
+ sizeof(struct efi_device_path_vendor) +
+ sizeof(struct efi_device_path),
+ (void **)&dp1);
+ if (ret != EFI_SUCCESS)
+ goto out_of_memory;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 *
+ sizeof(struct efi_device_path_vendor) +
+ sizeof(struct efi_device_path),
+ (void **)&dp2);
+ if (ret != EFI_SUCCESS)
+ goto out_of_memory;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 *
+ sizeof(struct efi_device_path_vendor) +
+ sizeof(struct efi_device_path),
+ (void **)&dp3);
+ if (ret != EFI_SUCCESS)
+ goto out_of_memory;
+
+ vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+ vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
+
+ boottime->copy_mem(&vendor_node.guid, &guid_vendor1,
+ sizeof(efi_guid_t));
+ boottime->copy_mem(dp1, &vendor_node,
+ sizeof(struct efi_device_path_vendor));
+ boottime->copy_mem(dp2, &vendor_node,
+ sizeof(struct efi_device_path_vendor));
+ boottime->copy_mem(dp3, &vendor_node,
+ sizeof(struct efi_device_path_vendor));
+
+ boottime->copy_mem(&vendor_node.guid, &guid_vendor2,
+ sizeof(efi_guid_t));
+ boottime->copy_mem(dp2 + sizeof(struct efi_device_path_vendor),
+ &vendor_node, sizeof(struct efi_device_path_vendor));
+ boottime->copy_mem(dp3 + sizeof(struct efi_device_path_vendor),
+ &vendor_node, sizeof(struct efi_device_path_vendor));
+
+ boottime->copy_mem(&vendor_node.guid, &guid_vendor3,
+ sizeof(efi_guid_t));
+ boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor),
+ &vendor_node, sizeof(struct efi_device_path_vendor));
+
+ end_node.type = DEVICE_PATH_TYPE_END;
+ end_node.sub_type = DEVICE_PATH_SUB_TYPE_END;
+ end_node.length = sizeof(struct efi_device_path);
+ boottime->copy_mem(dp1 + sizeof(struct efi_device_path_vendor),
+ &end_node, sizeof(struct efi_device_path));
+ boottime->copy_mem(dp2 + 2 * sizeof(struct efi_device_path_vendor),
+ &end_node, sizeof(struct efi_device_path));
+ boottime->copy_mem(dp3 + 3 * sizeof(struct efi_device_path_vendor),
+ &end_node, sizeof(struct efi_device_path));
+
+ ret = boottime->install_protocol_interface(&handle1,
+ &guid_device_path,
+ EFI_NATIVE_INTERFACE,
+ dp1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface(&handle1,
+ &guid_protocol,
+ EFI_NATIVE_INTERFACE,
+ &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface(&handle2,
+ &guid_device_path,
+ EFI_NATIVE_INTERFACE,
+ dp2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface(&handle2,
+ &guid_protocol,
+ EFI_NATIVE_INTERFACE,
+ &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface(&handle3,
+ &guid_device_path,
+ EFI_NATIVE_INTERFACE,
+ dp3);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+
+out_of_memory:
+ efi_st_error("Out of memory\n");
+ return EFI_ST_FAILURE;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ ret = boottime->uninstall_protocol_interface(handle1,
+ &guid_device_path,
+ dp1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface(handle1,
+ &guid_protocol,
+ &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface(handle2,
+ &guid_device_path,
+ dp2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface(handle2,
+ &guid_protocol,
+ &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface(handle3,
+ &guid_device_path,
+ dp3);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (dp1) {
+ ret = boottime->free_pool(dp1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (dp2) {
+ ret = boottime->free_pool(dp2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (dp3) {
+ ret = boottime->free_pool(dp3);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ */
+static int execute(void)
+{
+ struct efi_device_path *remaining_dp;
+ efi_handle_t handle;
+ /*
+ * This device path node ends with the letter 't' of 'u-boot'.
+ * The following '.bin' does not belong to the node but is
+ * helps to test the correct truncation.
+ */
+ struct {
+ struct efi_device_path dp;
+ u16 text[12];
+ } __packed dp_node = {
+ { DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_FILE_PATH,
+ sizeof(struct efi_device_path) + 12},
+ L"u-boot.bin",
+ };
+ u16 *string;
+ efi_status_t ret;
+ efi_uintn_t i, no_handles;
+ efi_handle_t *handles;
+ struct efi_device_path *dp;
+
+ /* Display all available device paths */
+ ret = boottime->locate_handle_buffer(BY_PROTOCOL,
+ &guid_device_path,
+ NULL, &no_handles, &handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot retrieve device path protocols.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ efi_st_printf("Installed device path protocols:\n");
+ for (i = 0; i < no_handles; ++i) {
+ ret = boottime->open_protocol(handles[i], &guid_device_path,
+ (void **)&dp, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Cannot open device path protocol.\n");
+ return EFI_ST_FAILURE;
+ }
+ string = device_path_to_text->convert_device_path_to_text(
+ dp, true, false);
+ if (!string) {
+ efi_st_error("ConvertDevicePathToText failed\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("%ps\n", string);
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * CloseProtocol cannot be called without agent handle.
+ * There is no need to close the device path protocol.
+ */
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Test ConvertDevicePathToText */
+ string = device_path_to_text->convert_device_path_to_text(
+ (struct efi_device_path *)dp2, true, false);
+ if (!string) {
+ efi_st_error("ConvertDevicePathToText failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (efi_st_strcmp_16_8(
+ string,
+ "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
+ ) {
+ efi_st_printf("dp2: %ps\n", string);
+ efi_st_error("Incorrect text from ConvertDevicePathToText\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Test ConvertDeviceNodeToText */
+ string = device_path_to_text->convert_device_node_to_text(
+ (struct efi_device_path *)&dp_node, true, false);
+ if (!string) {
+ efi_st_error("ConvertDeviceNodeToText failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (efi_st_strcmp_16_8(string, "u-boot")) {
+ efi_st_printf("dp_node: %ps\n", string);
+ efi_st_error(
+ "Incorrect conversion by ConvertDeviceNodeToText\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Test LocateDevicePath */
+ remaining_dp = (struct efi_device_path *)dp3;
+ ret = boottime->locate_device_path(&guid_protocol, &remaining_dp,
+ &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateDevicePath failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (handle != handle2) {
+ efi_st_error("LocateDevicePath returned wrong handle\n");
+ return EFI_ST_FAILURE;
+ }
+ string = device_path_to_text->convert_device_path_to_text(remaining_dp,
+ true, false);
+ if (!string) {
+ efi_st_error("ConvertDevicePathToText failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (efi_st_strcmp_16_8(string,
+ "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
+ ) {
+ efi_st_printf("remaining device path: %ps\n", string);
+ efi_st_error("LocateDevicePath: wrong remaining device path\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(devicepath) = {
+ .name = "device path",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_devicepath_util.c b/lib/efi_selftest/efi_selftest_devicepath_util.c
new file mode 100644
index 00000000..c846e057
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_devicepath_util.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_devicepath_util
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the device path utilities protocol.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+
+static efi_guid_t guid_device_path_utilities_protocol =
+ EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
+
+struct efi_device_path_utilities_protocol *dpu;
+
+/*
+ * Setup unit test.
+ *
+ * Locate the device path utilities protocol.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ int ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->locate_protocol(&guid_device_path_utilities_protocol,
+ NULL, (void **)&dpu);
+ if (ret != EFI_SUCCESS) {
+ dpu = NULL;
+ efi_st_error(
+ "Device path to text protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Create a device path consisting of a single media device node followed by an
+ * end node.
+ *
+ * @length: length of the media device node
+ * @dp: device path
+ * @return: status code
+ */
+static int create_single_node_device_path(unsigned int length,
+ struct efi_device_path **dp)
+{
+ struct efi_device_path *node;
+ efi_uintn_t len;
+ int ret;
+
+ node = dpu->create_device_node(DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_FILE_PATH, length);
+ if (!node) {
+ efi_st_error("CreateDeviceNode failed\n");
+ return EFI_ST_FAILURE;
+ }
+ *dp = dpu->append_device_node(NULL, node);
+ if (!*dp) {
+ efi_st_error("AppendDeviceNode failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(node);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(*dp);
+ if (len != length + 4) {
+ efi_st_error("Wrong device path length %u, expected %u\n",
+ (unsigned int)len, length);
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * In the test device paths are created, copied, and concatenated. The device
+ * path length is used as a measure of success.
+ */
+static int execute(void)
+{
+ struct efi_device_path *dp1;
+ struct efi_device_path *dp2;
+ struct efi_device_path *dp3;
+
+ efi_uintn_t len;
+ int ret;
+
+ /* IsDevicePathMultiInstance(NULL) */
+ if (dpu->is_device_path_multi_instance(NULL)) {
+ efi_st_error("IsDevicePathMultiInstance(NULL) returned true\n");
+ return EFI_ST_FAILURE;
+ }
+ /* GetDevicePathSize(NULL) */
+ len = dpu->get_device_path_size(NULL);
+ if (len) {
+ efi_st_error("Wrong device path length %u, expected 0\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ /* DuplicateDevicePath(NULL) */
+ dp1 = dpu->duplicate_device_path(NULL);
+ if (dp1) {
+ efi_st_error("DuplicateDevicePath(NULL) failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* AppendDevicePath(NULL, NULL) */
+ dp1 = dpu->append_device_path(NULL, NULL);
+ if (!dp1) {
+ efi_st_error("AppendDevicePath(NULL, NULL) failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(dp1);
+ if (len != 4) {
+ efi_st_error("Wrong device path length %u, expected 4\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp1);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* CreateDeviceNode */
+ ret = create_single_node_device_path(21, &dp1);
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+ ret = create_single_node_device_path(17, &dp2);
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+ /* AppendDevicePath */
+ dp3 = dpu->append_device_path(dp1, dp2);
+ if (!dp3) {
+ efi_st_error("AppendDevicePath failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (dp3 == dp1 || dp3 == dp2) {
+ efi_st_error("AppendDevicePath reused buffer\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(dp3);
+ /* 21 + 17 + 4 */
+ if (len != 42) {
+ efi_st_error("Wrong device path length %u, expected 42\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp2);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* AppendDeviceNode */
+ dp2 = dpu->append_device_node(dp1, dp3);
+ if (!dp2) {
+ efi_st_error("AppendDevicePath failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(dp2);
+ /* 21 + 21 + 4 */
+ if (len != 46) {
+ printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
+ efi_st_error("Wrong device path length %u, expected 46\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp1);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* IsDevicePathMultiInstance */
+ if (dpu->is_device_path_multi_instance(dp2)) {
+ printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
+ efi_st_error("IsDevicePathMultiInstance returned true\n");
+ return EFI_ST_FAILURE;
+ }
+ /* AppendDevicePathInstance */
+ dp1 = dpu->append_device_path_instance(dp2, dp3);
+ if (!dp1) {
+ efi_st_error("AppendDevicePathInstance failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(dp1);
+ /* 46 + 42 */
+ if (len != 88) {
+ efi_st_error("Wrong device path length %u, expected 88\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ /* IsDevicePathMultiInstance */
+ if (!dpu->is_device_path_multi_instance(dp1)) {
+ efi_st_error("IsDevicePathMultiInstance returned false\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp2);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp3);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* GetNextDevicePathInstance */
+ dp3 = dp1;
+ dp2 = dpu->get_next_device_path_instance(&dp1, &len);
+ if (!dp2) {
+ efi_st_error("GetNextDevicePathInstance failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!dp1) {
+ efi_st_error("GetNextDevicePathInstance no 2nd instance\n");
+ return EFI_ST_FAILURE;
+ }
+ if (len != 46) {
+ efi_st_error("Wrong device path length %u, expected 46\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ len = dpu->get_device_path_size(dp1);
+ if (len != 42) {
+ efi_st_error("Wrong device path length %u, expected 42\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp2);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ dp2 = dpu->get_next_device_path_instance(&dp1, &len);
+ if (!dp2) {
+ efi_st_error("GetNextDevicePathInstance failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (len != 42) {
+ efi_st_error("Wrong device path length %u, expected 46\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ if (dp1) {
+ efi_st_error("GetNextDevicePathInstance did not signal end\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Clean up */
+ ret = boottime->free_pool(dp2);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(dp3);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(dputil) = {
+ .name = "device path utilities protocol",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_disk_image.h b/lib/efi_selftest/efi_selftest_disk_image.h
new file mode 100644
index 00000000..a0e05866
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_disk_image.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Non-zero 8 byte strings of a disk image
+ *
+ * Generated with tools/file2include
+ */
+
+#define EFI_ST_DISK_IMG { 0x00010000, { \
+ {0x000001b8, "\x21\x5d\x53\xd1\x00\x00\x00\x00"}, /* !]S..... */ \
+ {0x000001c0, "\x02\x00\x01\x02\x02\x00\x01\x00"}, /* ........ */ \
+ {0x000001c8, "\x00\x00\x7f\x00\x00\x00\x00\x00"}, /* ........ */ \
+ {0x000001f8, "\x00\x00\x00\x00\x00\x00\x55\xaa"}, /* ......U. */ \
+ {0x00000200, "\xeb\x3c\x90\x6d\x6b\x66\x73\x2e"}, /* .<.mkfs. */ \
+ {0x00000208, "\x66\x61\x74\x00\x02\x04\x01\x00"}, /* fat..... */ \
+ {0x00000210, "\x02\x00\x02\x7f\x00\xf8\x01\x00"}, /* ........ */ \
+ {0x00000218, "\x20\x00\x40\x00\x00\x00\x00\x00"}, /* .@..... */ \
+ {0x00000220, "\x00\x00\x00\x00\x80\x00\x29\xc4"}, /* ......). */ \
+ {0x00000228, "\xc4\x88\x11\x55\x2d\x42\x4f\x4f"}, /* ...U-BOO */ \
+ {0x00000230, "\x54\x20\x54\x45\x53\x54\x46\x41"}, /* T TESTFA */ \
+ {0x00000238, "\x54\x31\x32\x20\x20\x20\x0e\x1f"}, /* T12 .. */ \
+ {0x00000240, "\xbe\x5b\x7c\xac\x22\xc0\x74\x0b"}, /* .[|.".t. */ \
+ {0x00000248, "\x56\xb4\x0e\xbb\x07\x00\xcd\x10"}, /* V....... */ \
+ {0x00000250, "\x5e\xeb\xf0\x32\xe4\xcd\x16\xcd"}, /* ^..2.... */ \
+ {0x00000258, "\x19\xeb\xfe\x54\x68\x69\x73\x20"}, /* ...This */ \
+ {0x00000260, "\x69\x73\x20\x6e\x6f\x74\x20\x61"}, /* is not a */ \
+ {0x00000268, "\x20\x62\x6f\x6f\x74\x61\x62\x6c"}, /* bootabl */ \
+ {0x00000270, "\x65\x20\x64\x69\x73\x6b\x2e\x20"}, /* e disk. */ \
+ {0x00000278, "\x20\x50\x6c\x65\x61\x73\x65\x20"}, /* Please */ \
+ {0x00000280, "\x69\x6e\x73\x65\x72\x74\x20\x61"}, /* insert a */ \
+ {0x00000288, "\x20\x62\x6f\x6f\x74\x61\x62\x6c"}, /* bootabl */ \
+ {0x00000290, "\x65\x20\x66\x6c\x6f\x70\x70\x79"}, /* e floppy */ \
+ {0x00000298, "\x20\x61\x6e\x64\x0d\x0a\x70\x72"}, /* and..pr */ \
+ {0x000002a0, "\x65\x73\x73\x20\x61\x6e\x79\x20"}, /* ess any */ \
+ {0x000002a8, "\x6b\x65\x79\x20\x74\x6f\x20\x74"}, /* key to t */ \
+ {0x000002b0, "\x72\x79\x20\x61\x67\x61\x69\x6e"}, /* ry again */ \
+ {0x000002b8, "\x20\x2e\x2e\x2e\x20\x0d\x0a\x00"}, /* ... ... */ \
+ {0x000003f8, "\x00\x00\x00\x00\x00\x00\x55\xaa"}, /* ......U. */ \
+ {0x00000400, "\xf8\xff\xff\x00\xf0\xff\x00\x00"}, /* ........ */ \
+ {0x00000600, "\xf8\xff\xff\x00\xf0\xff\x00\x00"}, /* ........ */ \
+ {0x00000800, "\x55\x2d\x42\x4f\x4f\x54\x20\x54"}, /* U-BOOT T */ \
+ {0x00000808, "\x45\x53\x54\x08\x00\x00\xaa\x56"}, /* EST....V */ \
+ {0x00000810, "\x84\x4c\x84\x4c\x00\x00\xaa\x56"}, /* .L.L...V */ \
+ {0x00000818, "\x84\x4c\x00\x00\x00\x00\x00\x00"}, /* .L...... */ \
+ {0x00000820, "\x41\x68\x00\x65\x00\x6c\x00\x6c"}, /* Ah.e.l.l */ \
+ {0x00000828, "\x00\x6f\x00\x0f\x00\xf1\x2e\x00"}, /* .o...... */ \
+ {0x00000830, "\x74\x00\x78\x00\x74\x00\x00\x00"}, /* t.x.t... */ \
+ {0x00000838, "\xff\xff\x00\x00\xff\xff\xff\xff"}, /* ........ */ \
+ {0x00000840, "\x48\x45\x4c\x4c\x4f\x20\x20\x20"}, /* HELLO */ \
+ {0x00000848, "\x54\x58\x54\x20\x00\x64\xd7\x46"}, /* TXT .d.F */ \
+ {0x00000850, "\x84\x4c\x84\x4c\x00\x00\xd7\x46"}, /* .L.L...F */ \
+ {0x00000858, "\x84\x4c\x03\x00\x0d\x00\x00\x00"}, /* .L...... */ \
+ {0x00005000, "\x48\x65\x6c\x6c\x6f\x20\x77\x6f"}, /* Hello wo */ \
+ {0x00005008, "\x72\x6c\x64\x21\x0a\x00\x00\x00"}, /* rld!.... */ \
+ {0, NULL} } }
diff --git a/lib/efi_selftest/efi_selftest_event_groups.c b/lib/efi_selftest/efi_selftest_event_groups.c
new file mode 100644
index 00000000..6dcde506
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_event_groups.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_event_groups
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the notification of group events and the
+ * following services:
+ * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
+ */
+
+#include <efi_selftest.h>
+
+#define GROUP_SIZE 16
+
+static struct efi_boot_services *boottime;
+static efi_guid_t event_group =
+ EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
+ 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ unsigned int *count = context;
+
+ if (count)
+ ++*count;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Create multiple events in an event group. Signal each event once and check
+ * that all events are notified once in each round.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ unsigned int counter[GROUP_SIZE] = {0};
+ struct efi_event *events[GROUP_SIZE];
+ size_t i, j;
+ efi_status_t ret;
+
+ for (i = 0; i < GROUP_SIZE; ++i) {
+ ret = boottime->create_event_ex(0, TPL_NOTIFY,
+ notify, (void *)&counter[i],
+ &event_group, &events[i]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to create event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ for (i = 0; i < GROUP_SIZE; ++i) {
+ ret = boottime->signal_event(events[i]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to signal event\n");
+ return EFI_ST_FAILURE;
+ }
+ for (j = 0; j < GROUP_SIZE; ++j) {
+ if (counter[j] != 2 * i + 1) {
+ efi_st_printf("i %u, j %u, count %u\n",
+ (unsigned int)i, (unsigned int)j,
+ (unsigned int)counter[j]);
+ efi_st_error("Notification function was not called\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Clear signaled state */
+ ret = boottime->check_event(events[j]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Event was not signaled\n");
+ return EFI_ST_FAILURE;
+ }
+ if (counter[j] != 2 * i + 1) {
+ efi_st_printf("i %u, j %u, count %u\n",
+ (unsigned int)i, (unsigned int)j,
+ (unsigned int)counter[j]);
+ efi_st_error(
+ "Notification function was called\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Call notification function */
+ ret = boottime->check_event(events[j]);
+ if (ret != EFI_NOT_READY) {
+ efi_st_error(
+ "Signaled state not cleared\n");
+ return EFI_ST_FAILURE;
+ }
+ if (counter[j] != 2 * i + 2) {
+ efi_st_printf("i %u, j %u, count %u\n",
+ (unsigned int)i, (unsigned int)j,
+ (unsigned int)counter[j]);
+ efi_st_error(
+ "Notification function not called\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ }
+
+ for (i = 0; i < GROUP_SIZE; ++i) {
+ ret = boottime->close_event(events[i]);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(eventgoups) = {
+ .name = "event groups",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c
new file mode 100644
index 00000000..1077cbdf
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_events.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test uses timer events to check the implementation
+ * of the following boottime services:
+ * CreateEvent, CloseEvent, WaitForEvent, CheckEvent, SetTimer.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int timer_ticks;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ unsigned int *count = context;
+
+ if (count)
+ ++*count;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK, notify, (void *)&timer_ticks,
+ &event_notify);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+ TPL_CALLBACK, notify, NULL, &event_wait);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ if (event_notify) {
+ ret = boottime->close_event(event_notify);
+ event_notify = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (event_wait) {
+ ret = boottime->close_event(event_wait);
+ event_wait = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Run a 100 ms single shot timer and check that it is called once
+ * while waiting for 100 ms periodic timer for two periods.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_uintn_t index;
+ efi_status_t ret;
+
+ /* Set 10 ms timer */
+ timer_ticks = 0;
+ ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 100 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Set some arbitrary non-zero value to make change detectable. */
+ index = 5;
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->check_event(event_wait);
+ if (ret != EFI_NOT_READY) {
+ efi_st_error("Signaled state was not cleared.\n");
+ efi_st_printf("ret = %u\n", (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ if (index != 0) {
+ efi_st_error("WaitForEvent returned wrong index\n");
+ return EFI_ST_FAILURE;
+ }
+ if (timer_ticks < 8 || timer_ticks > 12) {
+ efi_st_printf("Notification count periodic: %u\n", timer_ticks);
+ efi_st_error("Incorrect timing of events\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not cancel timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 10 ms timer */
+ timer_ticks = 0;
+ ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 100 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (timer_ticks != 1) {
+ efi_st_printf("Notification count single shot: %u\n",
+ timer_ticks);
+ efi_st_error("Single shot timer failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (timer_ticks != 1) {
+ efi_st_printf("Notification count stopped timer: %u\n",
+ timer_ticks);
+ efi_st_error("Stopped timer fired\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not cancel timer\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(events) = {
+ .name = "event services",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_exception.c b/lib/efi_selftest/efi_selftest_exception.c
new file mode 100644
index 00000000..6e900a35
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_exception.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_exception
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the handling of exceptions.
+ *
+ * The efi_selftest_miniapp_exception.efi application is loaded into memory
+ * and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the UEFI application */
+#include "efi_miniapp_file_image_exception.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+/* File device path for LoadImage() */
+static struct {
+ struct efi_device_path dp;
+ u16 filename[8];
+ struct efi_device_path end;
+} dp = {
+ {
+ DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_FILE_PATH,
+ sizeof(dp.dp) + sizeof(dp.filename),
+ },
+ L"bug.efi",
+ {
+ DEVICE_PATH_TYPE_END,
+ DEVICE_PATH_SUB_TYPE_END,
+ sizeof(dp.end),
+ }
+};
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ image_handle = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ ret = boottime->load_image(false, image_handle, &dp.dp, image,
+ img.length, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, NULL, NULL);
+
+ efi_st_error("Exception not triggered\n");
+
+ return EFI_ST_FAILURE;
+}
+
+EFI_UNIT_TEST(exception) = {
+ .name = "exception",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .on_request = true,
+};
diff --git a/lib/efi_selftest/efi_selftest_exitbootservices.c b/lib/efi_selftest/efi_selftest_exitbootservices.c
new file mode 100644
index 00000000..4fecd1b4
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_exitbootservices.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_exitbootservices
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks that the notification function of an
+ * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+static struct efi_event *event_notify;
+static unsigned int notification_count;
+
+/*
+ * Notification function, increments the notification count.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ unsigned int *count = context;
+
+ ++*count;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ notification_count = 0;
+ ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK, notify,
+ (void *)&notification_count,
+ &event_notify);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
+ * event has been called.
+ *
+ * Call ExitBootServices again and check that the notification function is
+ * not called again.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ if (notification_count != 1) {
+ efi_st_error("ExitBootServices was not notified\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_st_exit_boot_services();
+ if (notification_count != 1) {
+ efi_st_error("ExitBootServices was notified twice\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(exitbootservices) = {
+ .name = "ExitBootServices",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c
new file mode 100644
index 00000000..94d72d3f
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_fdt.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_pos
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
+ *
+ * The following services are tested:
+ * OutputString, TestString, SetAttribute.
+ */
+
+#include <efi_selftest.h>
+#include <linux/libfdt.h>
+
+static const struct efi_system_table *systemtab;
+static const struct efi_boot_services *boottime;
+static const char *fdt;
+
+/* This should be sufficient for */
+#define BUFFERSIZE 0x100000
+
+static const efi_guid_t fdt_guid = EFI_FDT_GUID;
+static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
+
+/*
+ * Convert FDT value to host endianness.
+ *
+ * @val FDT value
+ * @return converted value
+ */
+static uint32_t f2h(fdt32_t val)
+{
+ char *buf = (char *)&val;
+ char i;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ /* Swap the bytes */
+ i = buf[0]; buf[0] = buf[3]; buf[3] = i;
+ i = buf[1]; buf[1] = buf[2]; buf[2] = i;
+#endif
+ return *(uint32_t *)buf;
+}
+
+/*
+ * Return the value of a property of the FDT root node.
+ *
+ * @name name of the property
+ * @return value of the property
+ */
+static char *get_property(const u16 *property)
+{
+ struct fdt_header *header = (struct fdt_header *)fdt;
+ const fdt32_t *pos;
+ const char *strings;
+
+ if (!header)
+ return NULL;
+
+ if (f2h(header->magic) != FDT_MAGIC) {
+ printf("Wrong magic\n");
+ return NULL;
+ }
+
+ pos = (fdt32_t *)(fdt + f2h(header->off_dt_struct));
+ strings = fdt + f2h(header->off_dt_strings);
+
+ for (;;) {
+ switch (f2h(pos[0])) {
+ case FDT_BEGIN_NODE: {
+ char *c = (char *)&pos[1];
+ size_t i;
+
+ for (i = 0; c[i]; ++i)
+ ;
+ pos = &pos[2 + (i >> 2)];
+ break;
+ }
+ case FDT_PROP: {
+ struct fdt_property *prop = (struct fdt_property *)pos;
+ const char *label = &strings[f2h(prop->nameoff)];
+ efi_status_t ret;
+
+ /* Check if this is the property to be returned */
+ if (!efi_st_strcmp_16_8(property, label)) {
+ char *str;
+ efi_uintn_t len = f2h(prop->len);
+
+ if (!len)
+ return NULL;
+ /*
+ * The string might not be 0 terminated.
+ * It is safer to make a copy.
+ */
+ ret = boottime->allocate_pool(
+ EFI_LOADER_DATA, len + 1,
+ (void **)&str);
+ if (ret != EFI_SUCCESS) {
+ efi_st_printf("AllocatePool failed\n");
+ return NULL;
+ }
+ boottime->copy_mem(str, &pos[3], len);
+ str[len] = 0;
+
+ return str;
+ }
+
+ pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)];
+ break;
+ }
+ case FDT_NOP:
+ pos = &pos[1];
+ break;
+ default:
+ return NULL;
+ }
+ }
+}
+
+/**
+ * efi_st_get_config_table() - get configuration table
+ *
+ * @guid: GUID of the configuration table
+ * Return: pointer to configuration table or NULL
+ */
+static void *efi_st_get_config_table(const efi_guid_t *guid)
+{
+ size_t i;
+
+ for (i = 0; i < systab.nr_tables; i++) {
+ if (!guidcmp(guid, &systemtab->tables[i].guid))
+ return systemtab->tables[i].table;
+ }
+ return NULL;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ void *acpi;
+
+ systemtab = systable;
+ boottime = systable->boottime;
+
+ acpi = efi_st_get_config_table(&acpi_guid);
+ fdt = efi_st_get_config_table(&fdt_guid);
+
+ if (!fdt) {
+ efi_st_error("Missing device tree\n");
+ return EFI_ST_FAILURE;
+ }
+ if (acpi) {
+ efi_st_error("Found ACPI table and device tree\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ char *str;
+ efi_status_t ret;
+
+ str = get_property(L"compatible");
+ if (str) {
+ efi_st_printf("compatible: %s\n", str);
+ ret = boottime->free_pool(str);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ } else {
+ efi_st_printf("Missing property 'compatible'\n");
+ return EFI_ST_FAILURE;
+ }
+ str = get_property(L"serial-number");
+ if (str) {
+ efi_st_printf("serial-number: %s\n", str);
+ ret = boottime->free_pool(str);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(fdt) = {
+ .name = "device tree",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c
new file mode 100644
index 00000000..d64294ac
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_gop.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_gop
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the graphical output protocol.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+static efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+static struct efi_gop *gop;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->locate_protocol(&efi_gop_guid, NULL, (void **)&gop);
+ if (ret != EFI_SUCCESS) {
+ gop = NULL;
+ efi_st_printf("Graphical output protocol is not available.\n");
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ u32 i, max_mode;
+ efi_uintn_t size;
+ struct efi_gop_mode_info *info;
+
+ if (!gop)
+ return EFI_ST_SUCCESS;
+
+ if (!gop->mode) {
+ efi_st_error("EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE missing\n");
+ return EFI_ST_FAILURE;
+ }
+ max_mode = gop->mode->max_mode;
+ if (!max_mode) {
+ efi_st_error("No graphical mode available\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("Number of available modes: %u\n", max_mode);
+
+ for (i = 0; i < max_mode; ++i) {
+ ret = gop->query_mode(gop, i, &size, &info);
+ if (ret != EFI_SUCCESS) {
+ efi_st_printf("Could not query mode %u\n", i);
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("Mode %u: %u x %u\n",
+ i, info->width, info->height);
+ ret = boottime->free_pool(info);
+ if (ret != EFI_SUCCESS) {
+ efi_st_printf("FreePool failed");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(gop) = {
+ .name = "graphical output",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
new file mode 100644
index 00000000..f4b70f79
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_hii.c
@@ -0,0 +1,1060 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_hii
+ *
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ *
+ * Test HII database protocols
+ */
+
+#include <efi_selftest.h>
+#include "efi_selftest_hii_data.c"
+
+#define PRINT_TESTNAME efi_st_printf("%s:\n", __func__)
+
+static struct efi_boot_services *boottime;
+
+static const efi_guid_t hii_database_protocol_guid =
+ EFI_HII_DATABASE_PROTOCOL_GUID;
+static const efi_guid_t hii_string_protocol_guid =
+ EFI_HII_STRING_PROTOCOL_GUID;
+
+static struct efi_hii_database_protocol *hii_database_protocol;
+static struct efi_hii_string_protocol *hii_string_protocol;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ /* HII database protocol */
+ ret = boottime->locate_protocol(&hii_database_protocol_guid, NULL,
+ (void **)&hii_database_protocol);
+ if (ret != EFI_SUCCESS) {
+ hii_database_protocol = NULL;
+ efi_st_error("HII database protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* HII string protocol */
+ ret = boottime->locate_protocol(&hii_string_protocol_guid, NULL,
+ (void **)&hii_string_protocol);
+ if (ret != EFI_SUCCESS) {
+ hii_string_protocol = NULL;
+ efi_st_error("HII string protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * HII database protocol tests
+ */
+
+/**
+ * test_hii_database_new_package_list() - test creation and removal of
+ * package list
+ *
+ * This test adds a new package list and then tries to remove it using
+ * the provided handle.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_new_package_list(void)
+{
+ efi_hii_handle_t handle;
+ efi_status_t ret;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = hii_database_protocol->remove_package_list(hii_database_protocol,
+ handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * test_hii_database_update_package_list() - test update of package list
+ *
+ * This test adds a new package list and then tries to update it using
+ * another package list.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_update_package_list(void)
+{
+ efi_hii_handle_t handle = NULL;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = hii_database_protocol->update_package_list(hii_database_protocol,
+ handle,
+ (struct efi_hii_package_list_header *)packagelist2);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_database_list_package_lists() - test listing of package lists
+ *
+ * This test adds two package lists and then tries to enumerate them
+ * against different package types. We will get an array of handles.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_list_package_lists(void)
+{
+ efi_hii_handle_t handle1 = NULL, handle2 = NULL, *handles;
+ efi_uintn_t handles_size;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle1);
+ if (ret != EFI_SUCCESS || !handle1) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist2,
+ NULL, &handle2);
+ if (ret != EFI_SUCCESS || !handle2) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ /* TYPE_ALL */
+ handles = NULL;
+ handles_size = 0;
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_TYPE_ALL, NULL,
+ &handles_size, handles);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_TYPE_ALL, NULL,
+ &handles_size, handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
+
+ /* STRINGS */
+ handles = NULL;
+ handles_size = 0;
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_STRINGS, NULL,
+ &handles_size, handles);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_STRINGS, NULL,
+ &handles_size, handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
+
+ /* GUID */
+ handles = NULL;
+ handles_size = 0;
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_TYPE_GUID, &package_guid,
+ &handles_size, handles);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_TYPE_GUID, &package_guid,
+ &handles_size, handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+
+ /* KEYBOARD_LAYOUT */
+ handles = NULL;
+ handles_size = 0;
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL,
+ &handles_size, handles);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, handles_size,
+ (void **)&handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = hii_database_protocol->list_package_lists(hii_database_protocol,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL,
+ &handles_size, handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("list_package_lists returned %u\n",
+ (unsigned int)ret);
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+ ret = boottime->free_pool(handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ ret = EFI_ST_FAILURE;
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle1) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle1);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+ if (handle2) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle2);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_database_export_package_lists() - test export of package lists
+ *
+ * @Return: status code
+ */
+static int test_hii_database_export_package_lists(void)
+{
+ PRINT_TESTNAME;
+ /* export_package_lists() not implemented yet */
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * test_hii_database_register_package_notify() - test registration of
+ * notification function
+ *
+ * @Return: status code
+ */
+static int test_hii_database_register_package_notify(void)
+{
+ PRINT_TESTNAME;
+ /* register_package_notify() not implemented yet */
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * test_hii_database_unregister_package_notify() - test removal of
+ * notification function
+ *
+ * @Return: status code
+ */
+static int test_hii_database_unregister_package_notify(void)
+{
+ PRINT_TESTNAME;
+ /* unregsiter_package_notify() not implemented yet */
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * test_hii_database_find_keyboard_layouts() - test listing of
+ * all the keyboard layouts in the system
+ *
+ * This test adds two package lists, each of which has two keyboard layouts
+ * and then tries to enumerate them. We will get an array of handles.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_find_keyboard_layouts(void)
+{
+ efi_hii_handle_t handle1 = NULL, handle2 = NULL;
+ efi_guid_t *guids;
+ u16 guids_size;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle1);
+ if (ret != EFI_SUCCESS || !handle1) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist2,
+ NULL, &handle2);
+ if (ret != EFI_SUCCESS || !handle2) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ guids = NULL;
+ guids_size = 0;
+ ret = hii_database_protocol->find_keyboard_layouts(
+ hii_database_protocol, &guids_size, guids);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("find_keyboard_layouts returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, guids_size,
+ (void **)&guids);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_database_protocol->find_keyboard_layouts(
+ hii_database_protocol, &guids_size, guids);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("find_keyboard_layouts returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->free_pool(guids);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle1) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle1);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+ if (handle2) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle2);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_database_get_keyboard_layout() - test retrieval of keyboard layout
+ *
+ * This test adds two package lists, each of which has two keyboard layouts
+ * and then tries to get a handle to keyboard layout with a specific guid
+ * and the current one.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_get_keyboard_layout(void)
+{
+ efi_hii_handle_t handle1 = NULL, handle2 = NULL;
+ struct efi_hii_keyboard_layout *kb_layout;
+ u16 kb_layout_size;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle1);
+ if (ret != EFI_SUCCESS || !handle1) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist2,
+ NULL, &handle2);
+ if (ret != EFI_SUCCESS || !handle2) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ /* specific keyboard_layout(guid11) */
+ kb_layout = NULL;
+ kb_layout_size = 0;
+ ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
+ &kb_layout_guid11, &kb_layout_size, kb_layout);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("get_keyboard_layout returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, kb_layout_size,
+ (void **)&kb_layout);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
+ &kb_layout_guid11, &kb_layout_size, kb_layout);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("get_keyboard_layout returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->free_pool(kb_layout);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ goto out;
+ }
+
+ /* current */
+ kb_layout = NULL;
+ kb_layout_size = 0;
+ ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
+ NULL, &kb_layout_size, kb_layout);
+ if (ret != EFI_INVALID_PARAMETER) {
+ efi_st_error("get_keyboard_layout returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle1) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle1);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+ if (handle2) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle2);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_database_set_keyboard_layout() - test change of
+ * current keyboard layout
+ *
+ * @Return: status code
+ */
+static int test_hii_database_set_keyboard_layout(void)
+{
+ PRINT_TESTNAME;
+ /* set_keyboard_layout() not implemented yet */
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * test_hii_database_get_package_list_handle() - test retrieval of
+ * driver associated with a package list
+ *
+ * This test adds a package list, and then tries to get a handle to driver
+ * which is associated with a package list.
+ *
+ * @Return: status code
+ */
+static int test_hii_database_get_package_list_handle(void)
+{
+ efi_hii_handle_t handle = NULL;
+ efi_handle_t driver_handle;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ driver_handle = (efi_handle_t)0x12345678; /* dummy */
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ driver_handle, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ driver_handle = NULL;
+ ret = hii_database_protocol->get_package_list_handle(
+ hii_database_protocol, handle, &driver_handle);
+ if (ret != EFI_SUCCESS || driver_handle != (efi_handle_t)0x12345678) {
+ efi_st_error("get_package_list_handle returned %u, driver:%p\n",
+ (unsigned int)ret, driver_handle);
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+static int test_hii_database_protocol(void)
+{
+ int ret;
+
+ ret = test_hii_database_new_package_list();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_update_package_list();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_list_package_lists();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_export_package_lists();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_register_package_notify();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_unregister_package_notify();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_find_keyboard_layouts();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_get_keyboard_layout();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_set_keyboard_layout();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_database_get_package_list_handle();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * HII string protocol tests
+ */
+
+/**
+ * test_hii_string_new_string() - test creation of a new string entry
+ *
+ * This test adds a package list, and then tries to add a new string
+ * entry for a specific language.
+ *
+ * @Return: status code
+ */
+static int test_hii_string_new_string(void)
+{
+ efi_hii_handle_t handle = NULL;
+ efi_string_id_t id;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+ &id, (u8 *)"en-US",
+ L"Japanese", L"Japanese", NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("new_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ efi_st_printf("new string id is %u\n", id);
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_string_get_string() - test retrieval of a string entry
+ *
+ * This test adds a package list, create a new string entry and then tries
+ * to get it with its string id.
+ *
+ * @Return: status code
+ */
+static int test_hii_string_get_string(void)
+{
+ efi_hii_handle_t handle = NULL;
+ efi_string_id_t id;
+ efi_string_t string;
+ efi_uintn_t string_len;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+ &id, (u8 *)"en-US",
+ L"Japanese", L"Japanese", NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("new_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ string = NULL;
+ string_len = 0;
+ ret = hii_string_protocol->get_string(hii_string_protocol,
+ (u8 *)"en-US", handle, id, string, &string_len, NULL);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("get_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ string_len += sizeof(u16);
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, string_len,
+ (void **)&string);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_string_protocol->get_string(hii_string_protocol,
+ (u8 *)"en-US", handle, id, string, &string_len, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("get_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ if (efi_st_strcmp_16_8(string, "Japanese")) {
+ efi_st_error("get_string returned incorrect string\n");
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_string_set_string() - test change of a string entry
+ *
+ * This test adds a package list, create a new string entry and then tries
+ * to modify it.
+ *
+ * @Return: status code
+ */
+static int test_hii_string_set_string(void)
+{
+ efi_hii_handle_t handle = NULL;
+ efi_string_id_t id;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+ &id, (u8 *)"en-US",
+ L"Japanese", L"Japanese", NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("new_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ ret = hii_string_protocol->set_string(hii_string_protocol, handle,
+ id, (u8 *)"en-US",
+ L"Nihongo", NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("set_string returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_string_get_languages() - test listing of languages
+ *
+ * This test adds a package list, and then tries to enumerate languages
+ * in it. We will get an string of language names.
+ *
+ * @Return: status code
+ */
+static int test_hii_string_get_languages(void)
+{
+ efi_hii_handle_t handle = NULL;
+ u8 *languages;
+ efi_uintn_t languages_len;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ languages = NULL;
+ languages_len = 0;
+ ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
+ languages, &languages_len);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("get_languages returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
+ (void **)&languages);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
+ languages, &languages_len);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("get_languages returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ efi_st_printf("got languages are %s\n", languages);
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * test_hii_string_get_secondary_languages() - test listing of secondary
+ * languages
+ *
+ * This test adds a package list, and then tries to enumerate secondary
+ * languages with a specific language. We will get an string of language names.
+ *
+ * @Return: status code
+ */
+static int test_hii_string_get_secondary_languages(void)
+{
+ efi_hii_handle_t handle = NULL;
+ u8 *languages;
+ efi_uintn_t languages_len;
+ efi_status_t ret;
+ int result = EFI_ST_FAILURE;
+
+ PRINT_TESTNAME;
+ ret = hii_database_protocol->new_package_list(hii_database_protocol,
+ (struct efi_hii_package_list_header *)packagelist1,
+ NULL, &handle);
+ if (ret != EFI_SUCCESS || !handle) {
+ efi_st_error("new_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ languages = NULL;
+ languages_len = 0;
+ ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
+ handle, (u8 *)"en-US", languages, &languages_len);
+ if (ret == EFI_NOT_FOUND) {
+ efi_st_printf("no secondary languages\n");
+ result = EFI_ST_SUCCESS;
+ goto out;
+ }
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error("get_secondary_languages returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
+ (void **)&languages);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ goto out;
+ }
+ ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
+ handle, (u8 *)"en-US", languages, &languages_len);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("get_secondary_languages returned %u\n",
+ (unsigned int)ret);
+ goto out;
+ }
+
+ efi_st_printf("got secondary languages are %s\n", languages);
+
+ result = EFI_ST_SUCCESS;
+
+out:
+ if (handle) {
+ ret = hii_database_protocol->remove_package_list(
+ hii_database_protocol, handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("remove_package_list returned %u\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return result;
+}
+
+static int test_hii_string_protocol(void)
+{
+ int ret;
+
+ ret = test_hii_string_new_string();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_string_get_string();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_string_set_string();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_string_get_languages();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ ret = test_hii_string_get_secondary_languages();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success, EFI_ST_FAILURE for failure
+ */
+static int execute(void)
+{
+ int ret;
+
+ /* HII database protocol */
+ ret = test_hii_database_protocol();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ /* HII string protocol */
+ ret = test_hii_string_protocol();
+ if (ret != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(hii) = {
+ .name = "HII database protocols",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_hii_data.c b/lib/efi_selftest/efi_selftest_hii_data.c
new file mode 100644
index 00000000..d19f0682
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_hii_data.c
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * This file's test data is derived from UEFI SCT.
+ * The original copyright is attached below.
+ */
+
+/*
+ * Copyright 2006 - 2016 Unified EFI, Inc.<BR>
+ * Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD
+ * License which accompanies this distribution. The full text of the license
+ * may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ */
+
+#include <efi.h>
+
+#ifdef NOT_USED
+/*
+ * TODO: These macro's are not used as they appear only in
+ * "#ifdef NOT_USED" clauses. In the future, define them elsewhere.
+ */
+
+/* HII form */
+#define EFI_IFR_AND_OP 0x15
+#define EFI_IFR_END_OP 0x29
+#define EFI_IFR_BITWISE_AND_OP 0x35
+
+/* HII image */
+#define EFI_HII_IIBT_END 0x00
+#define EFI_HII_IIBT_IMAGE_1BIT 0x10
+#endif
+
+/* HII keyboard layout */
+#define EFI_NULL_MODIFIER 0x0000
+
+u8 packagelist1[] = {
+ // EFI_HII_PACKAGE_LIST_HEADER, length = 20
+ // SimpleFont, Font, GUID, Form, String, Image, DevicePath,
+ // (74) (110) 20 (8) 78 (67) (8)
+ // KeyboardLayout, End
+ // 192 4
+
+ 0x89, 0xcd, 0xab, 0x03, 0xf4, 0x03, 0x44, 0x70,
+ 0x81, 0xde, 0x99, 0xb1, 0x81, 0x20, 0xf7, 0x68, //16: guid
+ 0x3a, 0x01, 0x00, 0x00, // 4: total 314(0x13a)
+#ifdef NOT_USED /* TODO: simple font package not implemented yet */
+ //
+ // Simple Font Package 1, length = 74
+ //
+ 0x4A, 0x00, 0x00,
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ 1, 0,
+ 1, 0,
+ 0x55, 0x0, 0x1,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 0x77, 0x0, 0x2,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0, 0, 0,
+ //
+ // Font Package 1, length = 110
+ //
+ 0x6e, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_FONTS, // 1
+ 0x5c, 0x00, 0x00, 0x00, // 4: size of header
+ 0x5c, 0x00, 0x00, 0x00, // 4: offset
+ 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00,
+ 0xf5, 0x00, 0xec, 0xec, //10+2(pads)
+ 0xff, 0x33, 0xff, 0x44, // 4: font style
+ 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, //64
+ //
+ // Glyph block 1, length = 18
+ //
+ EFI_HII_GIBT_GLYPH_DEFAULT, // 1
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x99,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, //16: BitMapData
+ EFI_HII_GIBT_END, // 1
+#endif
+ //
+ // Guid Package 1, length = 20
+ //
+ 0x14, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_TYPE_GUID, // 1
+ 0x5a, 0xc9, 0x87, 0x03, 0x3, 0xd7, 0x46, 0x23,
+ 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8, //16: guid
+#ifdef NOT_USED /* TODO: form package not implemented yet */
+ //
+ // EFI_HII_PACKAGE_FORMS, length = 8
+ //
+ 0x08, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_FORMS, // 1
+ //
+ // Opcode 1, length = 4
+ //
+ EFI_IFR_AND_OP,
+ 0x82,
+ EFI_IFR_END_OP,
+ 0x02,
+ //
+#endif
+ // EFI_HII_PACKAGE_STRINGS, length = 78
+ //
+ 0x4e, 0x00, 0x00, // 3: length(header)
+ EFI_HII_PACKAGE_STRINGS, // 1: type(header)
+ 0x3c, 0x00, 0x00, 0x00, // 4: header_size
+ 0x3c, 0x00, 0x00, 0x00, // 4: string_offset
+ 0x00, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89, //32: language_window
+ 0x11, 0x00, 0x11, 0x22, 0x44, 0x55, 0x87, 0x89,
+ 0x22, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89,
+ 0x33, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89,
+ 0x01, 0x00, // 2: language name
+ 0x65, 0x6e, 0x2d, 0x55, 0x53, 0x3b, 0x7a, 0x68, //14: language
+ 0x2d, 0x48, 0x61, 0x6e, 0x74, 0x00, // "en-US;zh-Hant"
+ EFI_HII_SIBT_STRING_UCS2, // 1
+ 0x45, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x6C, 0x00,
+ 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x00, 0x00, //16: "English"
+ EFI_HII_SIBT_END, // 1
+#ifdef NOT_USED /* TODO: image package not implemented yet */
+ //
+ // EFI_HII_PACKAGE_IMAGES, length = 67
+ //
+ 0x43, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_IMAGES, // 1
+ 0x0c, 0x00, 0x00, 0x00, // 4: image info offset
+ 0x39, 0x00, 0x00, 0x00, // 4: palette info offset
+ EFI_HII_IIBT_IMAGE_1BIT, // 1
+ 0x01,
+ 0x0b, 0x00,
+ 0x13, 0x00,
+ 0x80, 0x00,
+ 0xc0, 0x00,
+ 0xe0, 0x00,
+ 0xf0, 0x00,
+ 0xf8, 0x00,
+ 0xfc, 0x00,
+ 0xfe, 0x00,
+ 0xff, 0x00,
+ 0xff, 0x80,
+ 0xff, 0xc0,
+ 0xff, 0xe0,
+ 0xfe, 0x00,
+ 0xef, 0x00,
+ 0xcf, 0x00,
+ 0x87, 0x80,
+ 0x07, 0x80,
+ 0x03, 0xc0,
+ 0x03, 0xc0,
+ 0x01, 0x80, //43
+ EFI_HII_IIBT_END, // 1
+ 0x01, 0x00,
+ 0x06, 0x00,
+ 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, //10
+ //
+ // EFI_HII_PACKAGE_DEVICE_PATH, length = 8
+ //
+ 0x08, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_DEVICE_PATH, // 1
+ 0x01, 0x23, 0x45, 0x66, // 4: dummy device path protocol
+ // instance address
+#endif
+ //
+ // Keyboard layout package 1, length = 192
+ 0xc0, 0x00, 0x00, // 3: length(header)
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT, // 1: type(header)
+ 0x02, 0x00, // 2: LayoutCount
+ //
+ // Layout 1, length = 93
+ //
+ 0x5d, 0x00, // 2: layout_length
+ 0x95, 0xe4, 0x40, 0x8d, 0xaa, 0xe2, 0x6f, 0x4c,
+ 0x89, 0x70, 0x68, 0x85, 0x09, 0xee, 0xc7, 0xd2, //16: guid
+ 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor_
+ // string_offset
+ 0x02, // 1: descriptor_count
+ //
+ // Descriptor 1, length = 16
+ //
+ 49, 0x00, 0x00, 0x00, // 4: key (EfiKeyD1)
+ 'q', 0x00, // 2: unicode
+ 'Q', 0x00, // 2: shifted_unicode
+ 0x00, 0x00, // 2: alt_gr_unicode
+ 0x00, 0x00, // 2: shifted_alt_gr_unicode
+ EFI_NULL_MODIFIER, 0x00, // 2: modifier
+ 0x03, 0x00, // 2: affected_attribute
+ //
+ // Descriptor 2, length = 16
+ //
+ 50, 0x00, 0x00, 0x00, // 4: key (EfiKeyD2)
+ 'w', 0x00, // 2: unicode
+ 'W', 0x00, // 2: shifted_unicode
+ 0x00, 0x00, // 2: alt_gr_unicode
+ 0x00, 0x00, // 2: shifted_alt_gr_unicode
+ EFI_NULL_MODIFIER, 0x00, // 2: modifier
+ 0x3, 0x0, // 2: affected_attribute
+ //
+ // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38
+ //
+ 0x01, 0x00, // 2: DescriptionCount
+ 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0,
+ //10: RFC3066 language code
+ ' ', 0x0, // 2: Space
+ 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0,
+ '1', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0,
+ //24: DescriptionString
+ //
+ // Layout 2, length = 93
+ //
+ 0x5d, 0x00, // 2: layout_length
+ 0x3e, 0x0b, 0xe6, 0x2a, 0xd6, 0xb9, 0xd8, 0x49,
+ 0x9a, 0x16, 0xc2, 0x48, 0xf1, 0xeb, 0xa8, 0xdb, //16: guid
+ 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor_
+ // string_offset
+ 0x02, // 1 Descriptor count
+ //
+ // Descriptor 1, length = 16
+ //
+ 51, 0x0, 0x0, 0x0, // 4: key (EfiKeyD3)
+ 'e', 0x00, // 2: unicode
+ 'E', 0x00, // 2: shifted_unicode
+ 0x00, 0x00, // 2: alt_gr_unicode
+ 0x00, 0x00, // 2: shifted_alt_gr_unicode
+ EFI_NULL_MODIFIER, 0x0, // 2: modifier
+ 0x3, 0x0, // 2: affected_attribute
+ //
+ // Descriptor 2, length = 16
+ //
+ 52, 0x0, 0x0, 0x0, // 4: key (EfiKeyD4)
+ 'r', 0x00, // 2: unicode
+ 'R', 0x00, // 2: shifted_unicode
+ 0x00, 0x00, // 2: alt_gr_unicode
+ 0x00, 0x00, // 2: shifted_alt_gr_unicode
+ EFI_NULL_MODIFIER, 0x0, // 2: modifier
+ 0x3, 0x0, // 2: affected_attribute
+ //
+ // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38
+ //
+ 0x01, 0x00, // 2: DescriptionCount
+ 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0,
+ //10: RFC3066 language code
+ ' ', 0x0, // 2: Space
+ 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0,
+ '2', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0,
+ //24: DescriptionString
+ //
+ // End of package list, length = 4
+ //
+ 0x4, 0x00, 0x00,
+ EFI_HII_PACKAGE_END
+};
+
+u8 packagelist2[] = {
+ // EFI_HII_PACKAGE_LIST_HEADER, length = 20
+ // SimpleFont, Font, GUID, KeyboardLayout, Form, End
+ // (74) (122) 20 192 (8) 4
+ 0xd3, 0xde, 0x85, 0x86, 0xce, 0x1b, 0xf3, 0x43,
+ 0xa2, 0x0c, 0xa3, 0x06, 0xec, 0x69, 0x72, 0xdd, //16
+ 0xec, 0x00, 0x00, 0x00, // 4: total 236(0xec)
+
+#ifdef NOT_USED /* TODO: simple font package not implemented yet */
+ //
+ // Simple Font Package 2, length = 74
+ //
+ 0x4A, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_SIMPLE_FONTS, // 1
+ 1, 0, // 2
+ 1, 0, // 2
+ 0x33, 0x0, 0, 1, 2, 3, 4, 5, 0, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, //22
+ 0x44, 0x0, 0x2, 2, 3, 4, 5, 6, 0, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, //22
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 0, 0, 0, //22
+ //
+ // Font Package 2, length = 122
+ //
+ 0x7A, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_FONTS, // 1
+ 0x5C, 0x00, 0x00, 0x00, // 4: size of header
+ 0x5C, 0x00, 0x00, 0x00, // 4: dummy offset
+ 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00,
+ 0xf5, 0x00, 0xec, 0xec, //10+2(pads)
+ 0xff, 0x11, 0xff, 0x22, // 4: font style
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, //64
+ //
+ // Glyph block 1, length = 30
+ //
+ EFI_HII_GIBT_GLYPH, // 1
+ 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00,
+ 0xf5, 0x00, //10
+ 0xff, 0x01, // 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, //16: BitMapData
+ EFI_HII_GIBT_END, // 1
+#endif
+ //
+ // Guid Package 1, length = 20
+ //
+ 0x14, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_TYPE_GUID, // 1
+ 0x5a, 0xc9, 0x87, 0x03, 0x3, 0xd7, 0x46, 0x23,
+ 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8, //16: guid
+ //
+ // Keyboard layout package 2, length = 192
+ 0xc0, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT, // 1
+ 0x02, 0x00, //0xec, 0xec, // 2: LayoutCount
+ //
+ // Layout 1, length = 93
+ //
+ 0x5d, 0x00, // 2: layout_length
+ 0x1f, 0x6a, 0xf5, 0xe0, 0x6b, 0xdf, 0x7e, 0x4a,
+ 0xa3, 0x9a, 0xe7, 0xa5, 0x19, 0x15, 0x45, 0xd6,//16: guid
+ 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor
+ // string offset
+ 0x02, // 1: descriptor_count
+ //
+ // Descriptor 1, length = 16
+ //
+ 32, 0x00, 0x00, 0x00, // 4: key (EfiKeyC1)
+ 'a', 0x00, // 2: unicode
+ 'A', 0x00, // 2: shifted_unicode
+ 0x00, 0x00, // 2: alt_gr_unicode
+ 0x00, 0x00, // 2: shifted_alt_gr_unic
+ EFI_NULL_MODIFIER, 0x00, // 2: modifier
+ 0x03, 0x00, // 2: affected_attribute
+ //
+ // Descriptor 2, length = 16
+ //
+ 33 /*EfiKeyC2*/, 0x00, 0x00, 0x00,
+ 's', 0x00,
+ 'S', 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ EFI_NULL_MODIFIER, 0x00,
+ 0x3, 0x0,
+ //
+ // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38
+ //
+ 0x01, 0x00, // 2: DescriptionCount
+ 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0,
+ //10: RFC3066 language code
+ ' ', 0x0, // 2: Space
+ 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0,
+ '3', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0,
+ //24: DescriptionString
+ //
+ // Layout 2, length = 93
+ //
+ 0x5d, 0x00, // 2: layout_length
+ 0xc9, 0x6a, 0xbe, 0x47, 0xcc, 0x54, 0xf9, 0x46,
+ 0xa2, 0x62, 0xd5, 0x3b, 0x25, 0x6a, 0xc, 0x34, //16: guid
+ 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor
+ // string_offset
+ 0x02, // 1: descriptor_count
+ //
+ // Descriptor 1, length = 16
+ //
+ 34 /*EfiKeyC3*/, 0x0, 0x0, 0x0,
+ 'd', 0x00,
+ 'D', 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ EFI_NULL_MODIFIER, 0x0,
+ 0x3, 0x0,
+ //
+ // Descriptor 2, length = 16
+ //
+ 35 /*EfiKeyC4*/, 0x0, 0x0, 0x0,
+ 'e', 0x00,
+ 'E', 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ EFI_NULL_MODIFIER, 0x0,
+ 0x3, 0x0,
+ //
+ // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38
+ //
+ 0x01, 0x00, // 2: DescriptionCount
+ 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0,
+ //10: RFC3066 language code
+ ' ', 0x0, // 2: Space
+ 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0,
+ '4', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0,
+ //24: DescriptionString
+#ifdef NOT_USED /* TODO: form package not implemented yet */
+ //
+ // EFI_HII_PACKAGE_FORMS, length = 8
+ //
+ 0x08, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_FORMS, // 1
+ //
+ // Opcode 1
+ //
+ EFI_IFR_BITWISE_AND_OP, // 1
+ 0x02, // 1
+ EFI_IFR_END_OP, // 1
+ 0x02, // 1
+#endif
+ //
+ // End of package list, length = 4
+ //
+ 0x4, 0x00, 0x00, // 3
+ EFI_HII_PACKAGE_END // 1
+};
+
+efi_guid_t packagelist_guid1 =
+ EFI_GUID(0x03abcd89, 0x03f4, 0x7044,
+ 0x81, 0xde, 0x99, 0xb1, 0x81, 0x20, 0xf7, 0x68);
+
+efi_guid_t packagelist_guid2 =
+ EFI_GUID(0x8685ded3, 0x1bce, 0x43f3,
+ 0xa2, 0x0c, 0xa3, 0x06, 0xec, 0x69, 0x72, 0xdd);
+
+efi_guid_t kb_layout_guid11 =
+ EFI_GUID(0x8d40e495, 0xe2aa, 0x4c6f,
+ 0x89, 0x70, 0x68, 0x85, 0x09, 0xee, 0xc7, 0xd2);
+
+efi_guid_t kb_layout_guid12 =
+ EFI_GUID(0x2ae60b3e, 0xb9d6, 0x49d8,
+ 0x9a, 0x16, 0xc2, 0x48, 0xf1, 0xeb, 0xa8, 0xdb);
+
+efi_guid_t kb_layout_guid21 =
+ EFI_GUID(0xe0f56a1f, 0xdf6b, 0x4a7e,
+ 0xa3, 0x9a, 0xe7, 0xa5, 0x19, 0x15, 0x45, 0xd6);
+
+efi_guid_t kb_layout_guid22 =
+ EFI_GUID(0x47be6ac9, 0x54cc, 0x46f9,
+ 0xa2, 0x62, 0xd5, 0x3b, 0x25, 0x6a, 0x0c, 0x34);
+
+efi_guid_t package_guid =
+ EFI_GUID(0x0387c95a, 0xd703, 0x2346,
+ 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8);
diff --git a/lib/efi_selftest/efi_selftest_loaded_image.c b/lib/efi_selftest/efi_selftest_loaded_image.c
new file mode 100644
index 00000000..5889ab12
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_loaded_image.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_loaded_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the Loaded Image Protocol.
+ */
+
+#include <efi_selftest.h>
+
+static efi_guid_t loaded_image_protocol_guid =
+ EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2,
+ 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b);
+static struct efi_boot_services *boottime;
+efi_handle_t image_handle;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+ image_handle = img_handle;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Verify that the loaded image protocol is installed on the image handle.
+ * Verify that the loaded image protocol points to the system table.
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t i, protocol_buffer_count = 0;
+ efi_guid_t **protocol_buffer = NULL;
+ bool found = false;
+ struct efi_loaded_image *loaded_image_protocol;
+
+ /*
+ * Get the GUIDs of all protocols installed on the handle.
+ */
+ ret = boottime->protocols_per_handle(image_handle, &protocol_buffer,
+ &protocol_buffer_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ProtocolsPerHandle failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!protocol_buffer_count || !protocol_buffer) {
+ efi_st_error("ProtocolsPerHandle returned no protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("%u protocols installed on image handle\n",
+ (unsigned int)protocol_buffer_count);
+ for (i = 0; i < protocol_buffer_count; ++i) {
+ if (memcmp(protocol_buffer[i], &loaded_image_protocol_guid,
+ sizeof(efi_guid_t)))
+ found = true;
+ }
+ if (!found) {
+ efi_st_printf("LoadedImageProtocol not found\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(protocol_buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Open the loaded image protocol.
+ */
+ ret = boottime->open_protocol(image_handle, &loaded_image_protocol_guid,
+ (void **)&loaded_image_protocol, NULL,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (loaded_image_protocol->revision !=
+ EFI_LOADED_IMAGE_PROTOCOL_REVISION) {
+ efi_st_printf("Incorrect revision\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!loaded_image_protocol->system_table ||
+ loaded_image_protocol->system_table->hdr.signature !=
+ EFI_SYSTEM_TABLE_SIGNATURE) {
+ efi_st_printf("System table reference missing\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(loadedimage) = {
+ .name = "loaded image",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_loadimage.c b/lib/efi_selftest/efi_selftest_loadimage.c
new file mode 100644
index 00000000..06a87df8
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_loadimage.c
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_loadimage
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the LoadImage and StartImage boot service.
+ *
+ * The efi_selftest_miniapp_exit.efi application is loaded via a file device
+ * path and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the efi_selftest_miniapp_exit.efi application */
+#include "efi_miniapp_file_image_exit.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+#define FILE_NAME L"app.efi"
+#define VOLUME_NAME L"EfiDisk"
+
+static struct efi_boot_services *boottime;
+static efi_handle_t handle_image;
+static efi_handle_t handle_volume;
+
+static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID;
+static const efi_guid_t guid_simple_file_system_protocol =
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static const efi_guid_t guid_file_info = EFI_FILE_INFO_GUID;
+static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+/* File info including file name */
+struct file_info {
+ struct efi_file_info info;
+ u16 file_name[sizeof(FILE_NAME)];
+};
+
+/* File system info including volume name */
+struct file_system_info {
+ struct efi_file_system_info info;
+ u16 file_name[sizeof(VOLUME_NAME)];
+};
+
+/* Compressed file image */
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Pointer to decompressed file image */
+static u8 *image;
+
+/* File info */
+static struct file_info priv_file_info = {
+ {
+ .size = sizeof(struct file_info),
+ .attribute = EFI_FILE_READ_ONLY,
+ },
+ FILE_NAME,
+};
+
+/* Pointer to file info */
+struct efi_file_info *file_info = &priv_file_info.info;
+
+/* Volume device path */
+static struct {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path end;
+} __packed dp_volume = {
+ .vendor = {
+ .dp = {
+ .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+ .length = sizeof(struct efi_device_path_vendor),
+ },
+ .guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
+ 0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
+ },
+ .end = {
+ .type = DEVICE_PATH_TYPE_END,
+ .sub_type = DEVICE_PATH_SUB_TYPE_END,
+ .length = sizeof(struct efi_device_path),
+ }
+};
+
+/* File device path */
+static struct {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path path;
+ u16 file[sizeof(FILE_NAME)];
+ struct efi_device_path end;
+} __packed dp_file = {
+ .vendor = {
+ .dp = {
+ .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+ .length = sizeof(struct efi_device_path_vendor),
+ },
+ .guid = EFI_GUID(0x4f9a0ebf, 0xa179, 0x88a6, 0x25, 0x68,
+ 0x10, 0x72, 0xb1, 0x93, 0x51, 0x71),
+ },
+ .path = {
+ .type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ .sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
+ .length = sizeof(struct efi_device_path) + sizeof(dp_file.file),
+ },
+ .file = FILE_NAME,
+ .end = {
+ .type = DEVICE_PATH_TYPE_END,
+ .sub_type = DEVICE_PATH_SUB_TYPE_END,
+ .length = sizeof(struct efi_device_path),
+ }
+};
+
+/* File system info */
+static struct file_system_info priv_file_system_info = {
+ {
+ .size = sizeof(struct file_system_info),
+ .read_only = true,
+ .volume_size = 0x100000,
+ .free_space = 0x0,
+ .block_size = 0x200,
+ },
+ VOLUME_NAME
+};
+
+/* Pointer to file system info */
+static struct efi_file_system_info *file_system_info =
+ &priv_file_system_info.info;
+
+/* Forward definitions of file and file system functions */
+static efi_status_t EFIAPI open_volume
+ (struct efi_simple_file_system_protocol *this,
+ struct efi_file_handle **root);
+
+static efi_status_t EFIAPI open
+ (struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes);
+
+static efi_status_t EFIAPI close(struct efi_file_handle *this);
+
+static efi_status_t EFIAPI delete(struct efi_file_handle *this);
+
+static efi_status_t EFIAPI read
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI write
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos);
+
+static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos);
+
+static efi_status_t EFIAPI getinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t *buffer_size, void *buffer);
+
+static efi_status_t EFIAPI setinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t buffer_size, void *buffer);
+
+static efi_status_t EFIAPI flush(struct efi_file_handle *this);
+
+/* Internal information about status of file system */
+static struct {
+ /* Difference of volume open count minus volume close count */
+ int volume_open_count;
+ /* Difference of file open count minus file close count */
+ int file_open_count;
+ /* File size */
+ u64 file_size;
+ /* Current position in file */
+ u64 file_pos;
+} priv;
+
+/* EFI_FILE_PROTOCOL for file */
+static struct efi_file_handle file = {
+ .rev = 0x00010000,
+ .open = open,
+ .close = close,
+ .delete = delete,
+ .read = read,
+ .write = write,
+ .getpos = getpos,
+ .setpos = setpos,
+ .getinfo = getinfo,
+ .setinfo = setinfo,
+ .flush = flush,
+};
+
+/* EFI_FILE_PROTOCOL for root directory */
+static struct efi_file_handle volume = {
+ .rev = 0x00010000,
+ .open = open,
+ .close = close,
+ .delete = delete,
+ .read = read,
+ .write = write,
+ .getpos = getpos,
+ .setpos = setpos,
+ .getinfo = getinfo,
+ .setinfo = setinfo,
+ .flush = flush,
+};
+
+/* EFI_SIMPLE_FILE_SYSTEM_PROTOCOL of the block device */
+struct efi_simple_file_system_protocol file_system = {
+ .rev = 0x00010000,
+ .open_volume = open_volume,
+};
+
+static efi_status_t EFIAPI open_volume
+ (struct efi_simple_file_system_protocol *this,
+ struct efi_file_handle **root)
+{
+ if (this != &file_system || !root)
+ return EFI_INVALID_PARAMETER;
+
+ *root = &volume;
+ priv.volume_open_count++;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI open
+ (struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode, u64 attributes)
+{
+ if (this != &volume)
+ return EFI_INVALID_PARAMETER;
+
+ *new_handle = &file;
+ priv.file_pos = 0;
+ priv.file_open_count++;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI close(struct efi_file_handle *this)
+{
+ if (this == &file)
+ priv.file_open_count--;
+ else if (this == &volume)
+ priv.volume_open_count--;
+ else
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI delete(struct efi_file_handle *this)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI read
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ if (priv.file_pos >= img.length)
+ *buffer_size = 0;
+ else if (priv.file_pos + *buffer_size > img.length)
+ *buffer_size = img.length - priv.file_pos;
+
+ boottime->copy_mem(buffer, &image[priv.file_pos], *buffer_size);
+ priv.file_pos += *buffer_size;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI write
+ (struct efi_file_handle *this, efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI getpos(struct efi_file_handle *this, u64 *pos)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ *pos = priv.file_pos;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI setpos(struct efi_file_handle *this, u64 pos)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ priv.file_pos = pos;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI getinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ if (this == &file) {
+ if (memcmp(info_type, &guid_file_info, sizeof(efi_guid_t)))
+ return EFI_INVALID_PARAMETER;
+ if (*buffer_size >= sizeof(struct file_info)) {
+ boottime->copy_mem(buffer, file_info,
+ sizeof(struct file_info));
+ } else {
+ *buffer_size = sizeof(struct file_info);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else if (this == &volume) {
+ if (memcmp(info_type, &guid_file_system_info,
+ sizeof(efi_guid_t)))
+ return EFI_INVALID_PARAMETER;
+ if (*buffer_size >= sizeof(struct file_system_info)) {
+ boottime->copy_mem(buffer, file_system_info,
+ sizeof(struct file_system_info));
+ } else {
+ *buffer_size = sizeof(struct file_system_info);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI setinfo
+ (struct efi_file_handle *this, const efi_guid_t *info_type,
+ efi_uintn_t buffer_size, void *buffer)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+static efi_status_t EFIAPI flush(struct efi_file_handle *this)
+{
+ if (this != &file)
+ return EFI_INVALID_PARAMETER;
+
+ return EFI_UNSUPPORTED;
+}
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ priv.file_size = img.length;
+ file_info->file_size = img.length;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Decompress application image and provide a handle for the in memory block
+ * device.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ handle_image = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ ret = boottime->install_protocol_interface
+ (&handle_volume, &guid_device_path, EFI_NATIVE_INTERFACE,
+ &dp_volume);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install device path\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_protocol_interface
+ (&handle_volume, &guid_simple_file_system_protocol,
+ EFI_NATIVE_INTERFACE, &file_system);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install simple file system protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Uninstall protocols and free memory.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret = EFI_ST_SUCCESS;
+
+ if (handle_volume) {
+ ret = boottime->uninstall_protocol_interface
+ (handle_volume, &guid_simple_file_system_protocol,
+ &file_system);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error
+ ("Failed to uninstall simple file system protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface
+ (handle_volume, &guid_device_path, &dp_volume);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error
+ ("Failed to uninstall device path protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ if (image) {
+ ret = boottime->free_pool(image);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ ret = boottime->load_image(false, handle_image, &dp_file.vendor.dp,
+ NULL, 0, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, NULL, NULL);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("Wrong return value from application\n");
+ return EFI_ST_FAILURE;
+ }
+
+ if (priv.file_open_count) {
+ efi_st_error("File open count = %d, expected 0\n",
+ priv.file_open_count);
+ return EFI_ST_FAILURE;
+ }
+ if (priv.volume_open_count) {
+ efi_st_error("Volume open count = %d, expected 0\n",
+ priv.volume_open_count);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(loadimage) = {
+ .name = "load image from file",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c
new file mode 100644
index 00000000..8edb1e4d
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_manageprotocols.c
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_manageprotocols
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * InstallProtocolInterface, UninstallProtocolInterface,
+ * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces,
+ * HandleProtocol, ProtocolsPerHandle,
+ * LocateHandle, LocateHandleBuffer.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * The test currently does not actually call the interface function.
+ * So this is just a dummy structure.
+ */
+struct interface {
+ void (EFIAPI * inc)(void);
+};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t guid1 =
+ EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
+ 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
+static efi_guid_t guid2 =
+ EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
+ 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
+static efi_guid_t guid3 =
+ EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9,
+ 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24);
+static efi_handle_t handle1;
+static efi_handle_t handle2;
+static struct interface interface1;
+static struct interface interface2;
+static struct interface interface3;
+static struct interface interface4;
+
+/*
+ * Find a handle in an array.
+ *
+ * @handle: handle to find
+ * @count: number of entries in the array
+ * @buffer: array to search
+ */
+efi_status_t find_in_buffer(efi_handle_t handle, size_t count,
+ efi_handle_t *buffer)
+{
+ size_t i;
+
+ for (i = 0; i < count; ++i) {
+ if (buffer[i] == handle)
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two handles and install two out of three protocol interfaces on each
+ * of them:
+ *
+ * handle1
+ * guid1 interface1
+ * guid3 interface3
+ * handle2
+ * guid1 interface4
+ * guid2 interface2
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ boottime = systable->boottime;
+
+ ret = boottime->install_protocol_interface(&handle1, &guid3,
+ EFI_NATIVE_INTERFACE,
+ &interface3);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!handle1) {
+ efi_st_error("InstallProtocolInterface failed to create handle\n");
+ return EFI_ST_FAILURE;
+ }
+ handle = handle1;
+ ret = boottime->install_protocol_interface(&handle1, &guid1,
+ EFI_NATIVE_INTERFACE,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (handle != handle1) {
+ efi_st_error("InstallProtocolInterface failed to use handle\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->install_multiple_protocol_interfaces(&handle2,
+ &guid1, &interface4, &guid2, &interface2, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallMultipleProtocolInterfaces failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!handle2 || handle1 == handle2) {
+ efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ */
+static int execute(void)
+{
+ struct interface *interface;
+ efi_status_t ret;
+ efi_handle_t *buffer;
+ size_t buffer_size;
+ efi_uintn_t count = 0;
+ efi_guid_t **prot_buffer;
+ efi_uintn_t prot_count;
+
+ /*
+ * Test HandleProtocol
+ */
+ ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("HandleProtocol failed to retrieve interface\n");
+ return EFI_ST_FAILURE;
+ }
+ if (interface != &interface3) {
+ efi_st_error("HandleProtocol returned wrong interface\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface);
+ if (ret == EFI_SUCCESS) {
+ efi_st_error("HandleProtocol returned not installed interface\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Test LocateHandleBuffer with AllHandles
+ */
+ ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
+ &count, &buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer with AllHandles failed\n");
+ return EFI_ST_FAILURE;
+ }
+ buffer_size = count;
+ ret = find_in_buffer(handle1, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed to locate new handle\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = find_in_buffer(handle2, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed to locate new handle\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Release buffer */
+ ret = boottime->free_pool(buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Test error handling in UninstallMultipleProtocols
+ *
+ * These are the installed protocol interfaces on handle 2:
+ *
+ * guid1 interface4
+ * guid2 interface2
+ *
+ * Try to uninstall more protocols than there are installed. This
+ * should return an error EFI_INVALID_PARAMETER. All deleted protocols
+ * should be reinstalled.
+ */
+ ret = boottime->uninstall_multiple_protocol_interfaces(
+ handle2,
+ &guid1, &interface4,
+ &guid2, &interface2,
+ &guid3, &interface3,
+ NULL);
+ if (ret != EFI_INVALID_PARAMETER) {
+ printf("%lx", ret);
+ efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Test LocateHandleBuffer with ByProtocol
+ *
+ * These are the handles with a guid1 protocol interface installed:
+ *
+ * handle1, handle2
+ */
+ count = buffer_size;
+ ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
+ &count, &buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed to locate new handles\n");
+ return EFI_ST_FAILURE;
+ }
+ if (count != 2) {
+ efi_st_error("UninstallMultipleProtocolInterfaces deleted handle\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = find_in_buffer(handle1, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed to locate new handle\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = find_in_buffer(handle2, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed to locate new handle\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Clear the buffer, we are reusing it it the next step. */
+ boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
+
+ /*
+ * Test LocateHandle with ByProtocol
+ */
+ count = buffer_size * sizeof(efi_handle_t);
+ ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL,
+ &count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandle with ByProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (count / sizeof(efi_handle_t) != 2) {
+ efi_st_error("LocateHandle failed to locate new handles\n");
+ return EFI_ST_FAILURE;
+ }
+ buffer_size = count;
+ ret = find_in_buffer(handle1, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandle failed to locate new handles\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = find_in_buffer(handle2, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandle failed to locate new handles\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Release buffer */
+ ret = boottime->free_pool(buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Test LocateProtocol
+ */
+ ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (interface != &interface1 && interface != &interface4) {
+ efi_st_error("LocateProtocol failed to locate protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Test UninstallMultipleProtocols
+ */
+ ret = boottime->uninstall_multiple_protocol_interfaces(
+ handle2,
+ &guid1, &interface4,
+ &guid2, &interface2,
+ NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Check that the protocols are really uninstalled.
+ */
+ count = buffer_size;
+ ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
+ &count, &buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("LocateHandleBuffer failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (count != 1) {
+ efi_st_error("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = find_in_buffer(handle1, count, buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to locate new handle\n");
+ return EFI_ST_FAILURE;
+ }
+ boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
+
+ /*
+ * Test ProtocolsPerHandle
+ */
+ ret = boottime->protocols_per_handle(handle1,
+ &prot_buffer, &prot_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to get protocols per handle\n");
+ return EFI_ST_FAILURE;
+ }
+ if (prot_count != 2) {
+ efi_st_error("Failed to get protocols per handle\n");
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(prot_buffer[0], &guid1, 16) &&
+ memcmp(prot_buffer[1], &guid1, 16)) {
+ efi_st_error("Failed to get protocols per handle\n");
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(prot_buffer[0], &guid3, 16) &&
+ memcmp(prot_buffer[1], &guid3, 16)) {
+ efi_st_error("Failed to get protocols per handle\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Release buffer */
+ ret = boottime->free_pool(prot_buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Uninstall remaining protocols
+ */
+ ret = boottime->uninstall_protocol_interface(handle1, &guid1,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface);
+ if (ret == EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_protocol_interface(handle1, &guid3,
+ &interface3);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(protserv) = {
+ .name = "manage protocols",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c
new file mode 100644
index 00000000..e71732dc
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_memory.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_memory
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following boottime services:
+ * AllocatePages, FreePages, GetMemoryMap
+ *
+ * The memory type used for the device tree is checked.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_NUM_PAGES 8
+
+static const efi_guid_t fdt_guid = EFI_FDT_GUID;
+static struct efi_boot_services *boottime;
+static u64 fdt_addr;
+
+/**
+ * setup() - setup unit test
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ size_t i;
+
+ boottime = systable->boottime;
+
+ for (i = 0; i < systable->nr_tables; ++i) {
+ if (!memcmp(&systable->tables[i].guid, &fdt_guid,
+ sizeof(efi_guid_t))) {
+ if (fdt_addr) {
+ efi_st_error("Duplicate device tree\n");
+ return EFI_ST_FAILURE;
+ }
+ fdt_addr = (uintptr_t)systable->tables[i].table;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * find_in_memory_map() - check matching memory map entry exists
+ *
+ * @memory_map: memory map
+ * @desc_size: number of memory map entries
+ * @addr: physical address to find in the map
+ * @type: expected memory type
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int find_in_memory_map(efi_uintn_t map_size,
+ struct efi_mem_desc *memory_map,
+ efi_uintn_t desc_size,
+ u64 addr, int memory_type)
+{
+ efi_uintn_t i;
+ bool found = false;
+
+ for (i = 0; map_size; ++i, map_size -= desc_size) {
+ struct efi_mem_desc *entry = &memory_map[i];
+
+ if (entry->physical_start != entry->virtual_start) {
+ efi_st_error("Physical and virtual addresses do not match\n");
+ return EFI_ST_FAILURE;
+ }
+
+ if (addr >= entry->physical_start &&
+ addr < entry->physical_start +
+ (entry->num_pages << EFI_PAGE_SHIFT)) {
+ if (found) {
+ efi_st_error("Duplicate memory map entry\n");
+ return EFI_ST_FAILURE;
+ }
+ found = true;
+ if (memory_type != entry->type) {
+ efi_st_error
+ ("Wrong memory type %d, expected %d\n",
+ entry->type, memory_type);
+ return EFI_ST_FAILURE;
+ }
+ }
+ }
+ if (!found) {
+ efi_st_error("Missing memory map entry\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * execute() - execute unit test
+ *
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ u64 p1;
+ u64 p2;
+ efi_uintn_t map_size = 0;
+ efi_uintn_t map_key;
+ efi_uintn_t desc_size;
+ u32 desc_version;
+ struct efi_mem_desc *memory_map;
+ efi_status_t ret;
+
+ /* Allocate two page ranges with different memory type */
+ ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_RUNTIME_SERVICES_CODE,
+ EFI_ST_NUM_PAGES, &p1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePages did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_RUNTIME_SERVICES_DATA,
+ EFI_ST_NUM_PAGES, &p2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePages did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Load memory map */
+ ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+ &desc_version);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error
+ ("GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Allocate extra space for newly allocated memory */
+ map_size += sizeof(struct efi_mem_desc);
+ ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+ (void **)&memory_map);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+ &desc_size, &desc_version);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetMemoryMap did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Check memory map entries */
+ if (find_in_memory_map(map_size, memory_map, desc_size, p1,
+ EFI_RUNTIME_SERVICES_CODE) != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+ if (find_in_memory_map(map_size, memory_map, desc_size, p2,
+ EFI_RUNTIME_SERVICES_DATA) != EFI_ST_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ /* Free memory */
+ ret = boottime->free_pages(p1, EFI_ST_NUM_PAGES);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePages did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pages(p2, EFI_ST_NUM_PAGES);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePages did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(memory_map);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool did not return EFI_SUCCESS\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Check memory reservation for the device tree */
+ if (fdt_addr &&
+ find_in_memory_map(map_size, memory_map, desc_size, fdt_addr,
+ EFI_BOOT_SERVICES_DATA) != EFI_ST_SUCCESS) {
+ efi_st_error
+ ("Device tree not marked as boot services data\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(memory) = {
+ .name = "memory",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_miniapp_exception.c b/lib/efi_selftest/efi_selftest_miniapp_exception.c
new file mode 100644
index 00000000..63c63d75
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_exception.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_miniapp_return
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt
+ *
+ * This EFI application triggers an exception.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+/*
+ * Entry point of the EFI application.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ * @return status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systable)
+{
+ struct efi_simple_text_output_protocol *con_out = systable->con_out;
+
+ con_out->output_string(con_out,
+ L"EFI application triggers exception.\n");
+
+#if defined(CONFIG_ARM)
+ /*
+ * 0xe7f...f. is undefined in ARM mode
+ * 0xde.. is undefined in Thumb mode
+ */
+ asm volatile (".word 0xe7f7defb\n");
+#elif defined(CONFIG_RISCV)
+ asm volatile (".word 0xffffffff\n");
+#elif defined(CONFIG_X86)
+ asm volatile (".word 0xffff\n");
+#endif
+ con_out->output_string(con_out, L"Exception not triggered.\n");
+ return EFI_ABORTED;
+}
diff --git a/lib/efi_selftest/efi_selftest_miniapp_exit.c b/lib/efi_selftest/efi_selftest_miniapp_exit.c
new file mode 100644
index 00000000..6b5cfb01
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_exit.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_miniapp_exit
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ *
+ * This EFI application is run by the StartImage selftest.
+ * It uses the Exit boot service to return.
+ */
+
+#include <common.h>
+#include <efi_selftest.h>
+
+static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+/**
+ * check_loaded_image_protocol() - check image_base/image_size
+ *
+ * Try to open the loaded image protocol. Check that this function is located
+ * between image_base and image_base + image_size.
+ *
+ * @image_handle: handle of the loaded image
+ * @systable: system table
+ * @return: status code
+ */
+static efi_status_t EFIAPI check_loaded_image_protocol
+ (efi_handle_t image_handle, struct efi_system_table *systable)
+{
+ struct efi_simple_text_output_protocol *cout = systable->con_out;
+ struct efi_boot_services *boottime = systable->boottime;
+ struct efi_loaded_image *loaded_image_protocol;
+ efi_status_t ret;
+
+ /*
+ * Open the loaded image protocol.
+ */
+ ret = boottime->open_protocol
+ (image_handle, &loaded_image_protocol_guid,
+ (void **)&loaded_image_protocol, NULL,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ cout->output_string(cout,
+ L"Could not open loaded image protocol");
+ return ret;
+ }
+ if ((void *)check_loaded_image_protocol <
+ loaded_image_protocol->image_base ||
+ (void *)check_loaded_image_protocol >=
+ loaded_image_protocol->image_base +
+ loaded_image_protocol->image_size) {
+ cout->output_string(cout,
+ L"Incorrect image_base or image_size\n");
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * Entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systable)
+{
+ struct efi_simple_text_output_protocol *con_out = systable->con_out;
+ efi_status_t ret;
+ u16 text[] = EFI_ST_SUCCESS_STR;
+
+ con_out->output_string(con_out, L"EFI application calling Exit\n");
+
+ if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
+ con_out->output_string(con_out,
+ L"Loaded image protocol missing\n");
+ ret = EFI_NOT_FOUND;
+ goto out;
+ }
+
+ /* This return value is expected by the calling test */
+ ret = EFI_UNSUPPORTED;
+out:
+ systable->boottime->exit(handle, ret, sizeof(text), text);
+
+ /*
+ * This statement should not be reached.
+ * To enable testing use a different return value.
+ */
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_selftest/efi_selftest_miniapp_return.c b/lib/efi_selftest/efi_selftest_miniapp_return.c
new file mode 100644
index 00000000..5709e39c
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_return.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_miniapp_return
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ *
+ * This EFI application is run by the StartImage selftest.
+ * It returns directly without calling the Exit boot service.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+/*
+ * Entry point of the EFI application.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ * @return status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systable)
+{
+ struct efi_simple_text_output_protocol *con_out = systable->con_out;
+
+ con_out->output_string(con_out,
+ L"EFI application returning w/o calling Exit\n");
+
+ /* The return value is checked by the calling test */
+ return EFI_INCOMPATIBLE_VERSION;
+}
diff --git a/lib/efi_selftest/efi_selftest_open_protocol.c b/lib/efi_selftest/efi_selftest_open_protocol.c
new file mode 100644
index 00000000..e3f351df
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_open_protocol.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_open_protocol
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks that open protocol information is correctly updated
+ * when calling:
+ * HandleProtocol, OpenProtocol, OpenProtocolInformation, CloseProtocol.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * The test currently does not actually call the interface function.
+ * So this is just a dummy structure.
+ */
+struct interface {
+ void (EFIAPI *inc)(void);
+};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t guid1 =
+ EFI_GUID(0x492a0e38, 0x1442, 0xf819,
+ 0x14, 0xaa, 0x4b, 0x8d, 0x09, 0xfe, 0x5a, 0xb9);
+static efi_handle_t handle1;
+static struct interface interface1;
+
+/*
+ * Setup unit test.
+ *
+ * Create a handle and install a protocol interface on it.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->install_protocol_interface(&handle1, &guid1,
+ EFI_NATIVE_INTERFACE,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("InstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!handle1) {
+ efi_st_error
+ ("InstallProtocolInterface failed to create handle\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ if (handle1) {
+ ret = boottime->uninstall_protocol_interface(handle1, &guid1,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallProtocolInterface failed\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Open the installed protocol twice via HandleProtocol() and once via
+ * OpenProtocol(EFI_OPEN_PROTOCOL_GET_PROTOCOL). Read the open protocol
+ * information and check the open counts. Finally close the protocol and
+ * check again.
+ */
+static int execute(void)
+{
+ void *interface;
+ struct efi_open_protocol_info_entry *entry_buffer;
+ efi_uintn_t entry_count;
+ efi_handle_t firmware_handle;
+ efi_status_t ret;
+
+ ret = boottime->handle_protocol(handle1, &guid1, &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("HandleProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (interface != &interface1) {
+ efi_st_error("HandleProtocol returned wrong interface\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol_information(handle1, &guid1,
+ &entry_buffer, &entry_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocolInformation failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (entry_count != 1) {
+ efi_st_error("Incorrect OpenProtocolInformation count\n");
+ efi_st_printf("Expected 1, got %u\n",
+ (unsigned int)entry_count);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(entry_buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->handle_protocol(handle1, &guid1, &interface);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("HandleProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol_information(handle1, &guid1,
+ &entry_buffer, &entry_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocolInformation failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (entry_count != 1) {
+ efi_st_error("Incorrect OpenProtocolInformation count\n");
+ efi_st_printf("Expected 1, got %u\n",
+ (unsigned int)entry_count);
+ return EFI_ST_FAILURE;
+ }
+ if (entry_buffer[0].open_count != 2) {
+ efi_st_error("Incorrect open count: expected 2 got %u\n",
+ entry_buffer[0].open_count);
+ return EFI_ST_FAILURE;
+ }
+ firmware_handle = entry_buffer[0].agent_handle;
+ ret = boottime->free_pool(entry_buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol(handle1, &guid1, &interface,
+ firmware_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol_information(handle1, &guid1,
+ &entry_buffer, &entry_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocolInformation failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (entry_count != 2) {
+ efi_st_error("Incorrect OpenProtocolInformation count\n");
+ efi_st_printf("Expected 2, got %u\n",
+ (unsigned int)entry_count);
+ return EFI_ST_FAILURE;
+ }
+ if (entry_buffer[0].open_count + entry_buffer[1].open_count != 3) {
+ efi_st_error("Incorrect open count: expected 3 got %u\n",
+ entry_buffer[0].open_count +
+ entry_buffer[1].open_count);
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(entry_buffer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->close_protocol(handle1, &guid1, firmware_handle, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("CloseProtocol failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->open_protocol_information(handle1, &guid1,
+ &entry_buffer, &entry_count);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("OpenProtocolInformation failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (entry_count) {
+ efi_st_error("Incorrect OpenProtocolInformation count\n");
+ efi_st_printf("Expected 0, got %u\n",
+ (unsigned int)entry_count);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(openprot) = {
+ .name = "open protocol",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_register_notify.c b/lib/efi_selftest/efi_selftest_register_notify.c
new file mode 100644
index 00000000..ad763dd6
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_register_notify.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_register_notify
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * InstallProtocolInterface, UninstallProtocolInterface,
+ * RegisterProtocolNotify, CreateEvent, CloseEvent.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * The test currently does not actually call the interface function.
+ * So this is just a dummy structure.
+ */
+struct interface {
+ void (EFIAPI * inc)(void);
+};
+
+struct context {
+ void *registration_key;
+ efi_uintn_t notify_count;
+ efi_uintn_t handle_count;
+ efi_handle_t *handles;
+};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t guid1 =
+ EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
+ 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
+static efi_guid_t guid2 =
+ EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
+ 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
+static struct context context;
+static struct efi_event *event;
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ struct context *cp = context;
+ efi_status_t ret;
+ efi_uintn_t handle_count;
+ efi_handle_t *handles;
+
+ cp->notify_count++;
+
+ for (;;) {
+ ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
+ cp->registration_key,
+ &handle_count, &handles);
+ if (ret != EFI_SUCCESS)
+ break;
+ cp->handle_count += handle_count;
+ cp->handles = handles;
+ }
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK, notify, &context,
+ &event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->register_protocol_notify(&guid1, event,
+ &context.registration_key);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not register event\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ if (event) {
+ ret = boottime->close_event(event);
+ event = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle1 = NULL, handle2 = NULL;
+ struct interface interface1, interface2;
+
+ ret = boottime->install_protocol_interface(&handle1, &guid1,
+ EFI_NATIVE_INTERFACE,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not install interface\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!context.notify_count) {
+ efi_st_error("install was not notified\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.notify_count > 1) {
+ efi_st_error("install was notified too often\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.handle_count != 1) {
+ efi_st_error("LocateHandle failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(context.handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ context.notify_count = 0;
+ ret = boottime->install_protocol_interface(&handle1, &guid2,
+ EFI_NATIVE_INTERFACE,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not install interface\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.notify_count) {
+ efi_st_error("wrong protocol was notified\n");
+ return EFI_ST_FAILURE;
+ }
+ context.notify_count = 0;
+ ret = boottime->reinstall_protocol_interface(handle1, &guid1,
+ &interface1, &interface2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not reinstall interface\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!context.notify_count) {
+ efi_st_error("reinstall was not notified\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.notify_count > 1) {
+ efi_st_error("reinstall was notified too often\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.handle_count != 2) {
+ efi_st_error("LocateHandle failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(context.handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ context.notify_count = 0;
+ ret = boottime->install_protocol_interface(&handle2, &guid1,
+ EFI_NATIVE_INTERFACE,
+ &interface1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not install interface\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!context.notify_count) {
+ efi_st_error("install was not notified\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.notify_count > 1) {
+ efi_st_error("install was notified too often\n");
+ return EFI_ST_FAILURE;
+ }
+ if (context.handle_count != 3) {
+ efi_st_error("LocateHandle failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(context.handles);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("FreePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->uninstall_multiple_protocol_interfaces
+ (handle1, &guid1, &interface2,
+ &guid2, &interface1, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->uninstall_multiple_protocol_interfaces
+ (handle2, &guid1, &interface1, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(regprotnot) = {
+ .name = "register protocol notify",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_rtc.c b/lib/efi_selftest/efi_selftest_rtc.c
new file mode 100644
index 00000000..6f7035de
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_rtc.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_rtc
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the real time clock runtime services.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_NO_RTC "Could not read real time clock\n"
+#define EFI_ST_NO_RTC_SET "Could not set real time clock\n"
+
+static struct efi_runtime_services *runtime;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ runtime = systable->runtime;
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Read and display current time.
+ * Set a new value and read it back.
+ * Set the real time clock back the current time.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ struct efi_time tm_old;
+#ifdef CONFIG_EFI_SET_TIME
+ struct efi_time tm, tm_new = {
+ .year = 2017,
+ .month = 5,
+ .day = 19,
+ .hour = 13,
+ .minute = 47,
+ .second = 53,
+ };
+#endif
+
+ /* Display current time */
+ ret = runtime->get_time(&tm_old, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error(EFI_ST_NO_RTC);
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("Time according to real time clock: "
+ "%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
+ tm_old.year, tm_old.month, tm_old.day,
+ tm_old.hour, tm_old.minute, tm_old.second);
+#ifdef CONFIG_EFI_SET_TIME
+ ret = runtime->set_time(&tm_new);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error(EFI_ST_NO_RTC_SET);
+ return EFI_ST_FAILURE;
+ }
+ ret = runtime->get_time(&tm, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error(EFI_ST_NO_RTC);
+ return EFI_ST_FAILURE;
+ }
+ if (tm.year != tm_new.year ||
+ tm.month != tm_new.month ||
+ tm.day != tm_new.day ||
+ tm.hour != tm_new.hour ||
+ tm.minute != tm_new.minute ||
+ tm.second < tm_new.second ||
+ tm.second > tm_new.second + 2) {
+ efi_st_error(EFI_ST_NO_RTC_SET);
+ return EFI_ST_FAILURE;
+ }
+ /* Set time back to old value */
+ ret = runtime->set_time(&tm_old);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error(EFI_ST_NO_RTC_SET);
+ return EFI_ST_FAILURE;
+ }
+#endif
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(rtc) = {
+ .name = "real time clock",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
new file mode 100644
index 00000000..a4e5a50f
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_set_virtual_address_map.c
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the notification of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+ * and the following services: SetVirtualAddressMap, ConvertPointer.
+ */
+
+#include <efi_selftest.h>
+
+static const struct efi_boot_services *boottime;
+static const struct efi_runtime_services *runtime;
+static struct efi_event *event;
+static struct efi_mem_desc *memory_map;
+static efi_uintn_t map_size;
+static efi_uintn_t desc_size;
+static u32 desc_version;
+static u64 page1;
+static u64 page2;
+static u32 notify_call_count;
+static bool convert_pointer_failed;
+
+/**
+ * notify () - notification function
+ *
+ * This function is called when the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event
+ * occurs. The correct output of ConvertPointer() is checked.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ void *addr;
+ efi_status_t ret;
+
+ ++notify_call_count;
+
+ addr = (void *)(uintptr_t)page1;
+ ret = runtime->convert_pointer(0, &addr);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ConvertPointer failed\n");
+ convert_pointer_failed = true;
+ return;
+ }
+ if ((uintptr_t)addr != page1 + EFI_PAGE_SIZE) {
+ efi_st_error("ConvertPointer wrong address\n");
+ convert_pointer_failed = true;
+ return;
+ }
+
+ addr = (void *)(uintptr_t)page2;
+ ret = runtime->convert_pointer(0, &addr);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ConvertPointer failed\n");
+ convert_pointer_failed = true;
+ return;
+ }
+ if ((uintptr_t)addr != page2 + 2 * EFI_PAGE_SIZE) {
+ efi_st_error("ConvertPointer wrong address\n");
+ convert_pointer_failed = true;
+ }
+}
+
+/**
+ * setup() - setup unit test
+ *
+ * The memory map is read. Boottime only entries are deleted. Two entries for
+ * newly allocated pages are added. For these virtual addresses deviating from
+ * the physical addresses are set.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_uintn_t map_key;
+ efi_status_t ret;
+ struct efi_mem_desc *end, *pos1, *pos2;
+
+ boottime = systable->boottime;
+ runtime = systable->runtime;
+
+ ret = boottime->create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+ TPL_CALLBACK, notify, NULL,
+ &event);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+ &desc_version);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ efi_st_error(
+ "GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Allocate extra space for newly allocated memory */
+ map_size += 3 * sizeof(struct efi_mem_desc);
+ ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+ (void **)&memory_map);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePool failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+ &desc_size, &desc_version);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetMemoryMap failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_BOOT_SERVICES_DATA, 2, &page1);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePages failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_BOOT_SERVICES_DATA, 3, &page2);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("AllocatePages failed\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Remove entries not relevant for runtime from map */
+ end = (struct efi_mem_desc *)((u8 *)memory_map + map_size);
+ for (pos1 = memory_map, pos2 = memory_map;
+ pos2 < end; ++pos2) {
+ switch (pos2->type) {
+ case EFI_LOADER_CODE:
+ case EFI_LOADER_DATA:
+ case EFI_BOOT_SERVICES_CODE:
+ case EFI_BOOT_SERVICES_DATA:
+ case EFI_CONVENTIONAL_MEMORY:
+ continue;
+ }
+ memcpy(pos1, pos2, desc_size);
+ ++pos1;
+ }
+
+ /*
+ * Add entries with virtual addresses deviating from the physical
+ * addresses. By choosing virtual address ranges within the allocated
+ * physical pages address space collisions are avoided.
+ */
+ pos1->type = EFI_RUNTIME_SERVICES_DATA;
+ pos1->reserved = 0;
+ pos1->physical_start = page1;
+ pos1->virtual_start = page1 + EFI_PAGE_SIZE;
+ pos1->num_pages = 1;
+ pos1->attribute = EFI_MEMORY_RUNTIME;
+ ++pos1;
+
+ pos1->type = EFI_RUNTIME_SERVICES_DATA;
+ pos1->reserved = 0;
+ pos1->physical_start = page2;
+ pos1->virtual_start = page2 + 2 * EFI_PAGE_SIZE;
+ pos1->num_pages = 1;
+ pos1->attribute = EFI_MEMORY_RUNTIME;
+ ++pos1;
+
+ map_size = (u8 *)pos1 - (u8 *)memory_map;
+
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * execute() - execute unit test
+ *
+ * SetVirtualAddressMap() is called with the memory map prepared in setup().
+ *
+ * The triggering of the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event is checked via
+ * the call count of the notification function.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+
+ ret = runtime->set_virtual_address_map(map_size, desc_size,
+ desc_version, memory_map);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVirtualAddressMap failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notify_call_count != 1) {
+ efi_st_error("EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE triggered %d times\n",
+ notify_call_count);
+ return EFI_ST_FAILURE;
+ }
+ if (convert_pointer_failed)
+ return EFI_ST_FAILURE;
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(virtaddrmap) = {
+ .name = "virtual address map",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c
new file mode 100644
index 00000000..9797ecaf
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_snp.c
@@ -0,0 +1,485 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_snp
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test covers the Simple Network Protocol as well as
+ * the CopyMem and SetMem boottime services.
+ *
+ * A DHCP discover message is sent. The test is successful if a
+ * DHCP reply is received.
+ *
+ * TODO: Once ConnectController and DisconnectController are implemented
+ * we should connect our code as controller.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * MAC address for broadcasts
+ */
+static const u8 BROADCAST_MAC[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+struct dhcp_hdr {
+ u8 op;
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+ u8 htype;
+# define HWT_ETHER 1
+ u8 hlen;
+# define HWL_ETHER 6
+ u8 hops;
+ u32 xid;
+ u16 secs;
+ u16 flags;
+#define DHCP_FLAGS_UNICAST 0x0000
+#define DHCP_FLAGS_BROADCAST 0x0080
+ u32 ciaddr;
+ u32 yiaddr;
+ u32 siaddr;
+ u32 giaddr;
+ u8 chaddr[16];
+ u8 sname[64];
+ u8 file[128];
+};
+
+/*
+ * Message type option.
+ */
+#define DHCP_MESSAGE_TYPE 0x35
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+
+struct dhcp {
+ struct ethernet_hdr eth_hdr;
+ struct ip_udp_hdr ip_udp;
+ struct dhcp_hdr dhcp_hdr;
+ u8 opt[128];
+} __packed;
+
+static struct efi_boot_services *boottime;
+static struct efi_simple_network *net;
+static struct efi_event *timer;
+static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
+/* IP packet ID */
+static unsigned int net_ip_id;
+
+/*
+ * Compute the checksum of the IP header. We cover even values of length only.
+ * We cannot use net/checksum.c due to different CFLAGS values.
+ *
+ * @buf: IP header
+ * @len: length of header in bytes
+ * @return: checksum
+ */
+static unsigned int efi_ip_checksum(const void *buf, size_t len)
+{
+ size_t i;
+ u32 sum = 0;
+ const u16 *pos = buf;
+
+ for (i = 0; i < len; i += 2)
+ sum += *pos++;
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += sum >> 16;
+ sum = ~sum & 0xffff;
+
+ return sum;
+}
+
+/*
+ * Transmit a DHCPDISCOVER message.
+ */
+static efi_status_t send_dhcp_discover(void)
+{
+ efi_status_t ret;
+ struct dhcp p = {};
+
+ /*
+ * Fill Ethernet header
+ */
+ boottime->copy_mem(p.eth_hdr.et_dest, (void *)BROADCAST_MAC, ARP_HLEN);
+ boottime->copy_mem(p.eth_hdr.et_src, &net->mode->current_address,
+ ARP_HLEN);
+ p.eth_hdr.et_protlen = htons(PROT_IP);
+ /*
+ * Fill IP header
+ */
+ p.ip_udp.ip_hl_v = 0x45;
+ p.ip_udp.ip_len = htons(sizeof(struct dhcp) -
+ sizeof(struct ethernet_hdr));
+ p.ip_udp.ip_id = htons(++net_ip_id);
+ p.ip_udp.ip_off = htons(IP_FLAGS_DFRAG);
+ p.ip_udp.ip_ttl = 0xff; /* time to live */
+ p.ip_udp.ip_p = IPPROTO_UDP;
+ boottime->set_mem(&p.ip_udp.ip_dst, 4, 0xff);
+ p.ip_udp.ip_sum = efi_ip_checksum(&p.ip_udp, IP_HDR_SIZE);
+
+ /*
+ * Fill UDP header
+ */
+ p.ip_udp.udp_src = htons(68);
+ p.ip_udp.udp_dst = htons(67);
+ p.ip_udp.udp_len = htons(sizeof(struct dhcp) -
+ sizeof(struct ethernet_hdr) -
+ sizeof(struct ip_hdr));
+ /*
+ * Fill DHCP header
+ */
+ p.dhcp_hdr.op = BOOTREQUEST;
+ p.dhcp_hdr.htype = HWT_ETHER;
+ p.dhcp_hdr.hlen = HWL_ETHER;
+ p.dhcp_hdr.flags = htons(DHCP_FLAGS_UNICAST);
+ boottime->copy_mem(&p.dhcp_hdr.chaddr,
+ &net->mode->current_address, ARP_HLEN);
+ /*
+ * Fill options
+ */
+ p.opt[0] = 0x63; /* DHCP magic cookie */
+ p.opt[1] = 0x82;
+ p.opt[2] = 0x53;
+ p.opt[3] = 0x63;
+ p.opt[4] = DHCP_MESSAGE_TYPE;
+ p.opt[5] = 0x01; /* length */
+ p.opt[6] = DHCPDISCOVER;
+ p.opt[7] = 0x39; /* maximum message size */
+ p.opt[8] = 0x02; /* length */
+ p.opt[9] = 0x02; /* 576 bytes */
+ p.opt[10] = 0x40;
+ p.opt[11] = 0xff; /* end of options */
+
+ /*
+ * Transmit DHCPDISCOVER message.
+ */
+ ret = net->transmit(net, 0, sizeof(struct dhcp), &p, NULL, NULL, 0);
+ if (ret != EFI_SUCCESS)
+ efi_st_error("Sending a DHCP request failed\n");
+ else
+ efi_st_printf("DHCP Discover\n");
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create a 1 s periodic timer.
+ * Start the network driver.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ /*
+ * Create a timer event.
+ */
+ ret = boottime->create_event(EVT_TIMER, TPL_CALLBACK, NULL, NULL,
+ &timer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to create event\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Set timer period to 1s.
+ */
+ ret = boottime->set_timer(timer, EFI_TIMER_PERIODIC, 10000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Find an interface implementing the SNP protocol.
+ */
+ ret = boottime->locate_protocol(&efi_net_guid, NULL, (void **)&net);
+ if (ret != EFI_SUCCESS) {
+ net = NULL;
+ efi_st_error("Failed to locate simple network protocol\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Check hardware address size.
+ */
+ if (!net->mode) {
+ efi_st_error("Mode not provided\n");
+ return EFI_ST_FAILURE;
+ }
+ if (net->mode->hwaddr_size != ARP_HLEN) {
+ efi_st_error("HwAddressSize = %u, expected %u\n",
+ net->mode->hwaddr_size, ARP_HLEN);
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Check that WaitForPacket event exists.
+ */
+ if (!net->wait_for_packet) {
+ efi_st_error("WaitForPacket event missing\n");
+ return EFI_ST_FAILURE;
+ }
+ if (net->mode->state == EFI_NETWORK_INITIALIZED) {
+ /*
+ * Shut down network adapter.
+ */
+ ret = net->shutdown(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to shut down network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (net->mode->state == EFI_NETWORK_STARTED) {
+ /*
+ * Stop network adapter.
+ */
+ ret = net->stop(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to stop network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ /*
+ * Start network adapter.
+ */
+ ret = net->start(net);
+ if (ret != EFI_SUCCESS && ret != EFI_ALREADY_STARTED) {
+ efi_st_error("Failed to start network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ if (net->mode->state != EFI_NETWORK_STARTED) {
+ efi_st_error("Failed to start network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Initialize network adapter.
+ */
+ ret = net->initialize(net, 0, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to initialize network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ if (net->mode->state != EFI_NETWORK_INITIALIZED) {
+ efi_st_error("Failed to initialize network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * A DHCP discover message is sent. The test is successful if a
+ * DHCP reply is received within 10 seconds.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ struct efi_event *events[2];
+ efi_uintn_t index;
+ union {
+ struct dhcp p;
+ u8 b[PKTSIZE];
+ } buffer;
+ struct efi_mac_address srcaddr;
+ struct efi_mac_address destaddr;
+ size_t buffer_size;
+ u8 *addr;
+
+ /*
+ * The timeout is to occur after 10 s.
+ */
+ unsigned int timeout = 10;
+
+ /* Setup may have failed */
+ if (!net || !timer) {
+ efi_st_error("Cannot execute test after setup failure\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /*
+ * Send DHCP discover message
+ */
+ ret = send_dhcp_discover();
+ if (ret != EFI_SUCCESS)
+ return EFI_ST_FAILURE;
+
+ /*
+ * If we would call WaitForEvent only with the WaitForPacket event,
+ * our code would block until a packet is received which might never
+ * occur. By calling WaitFor event with both a timer event and the
+ * WaitForPacket event we can escape this blocking situation.
+ *
+ * If the timer event occurs before we have received a DHCP reply
+ * a further DHCP discover message is sent.
+ */
+ events[0] = timer;
+ events[1] = net->wait_for_packet;
+ for (;;) {
+ u32 int_status;
+
+ /*
+ * Wait for packet to be received or timer event.
+ */
+ boottime->wait_for_event(2, events, &index);
+ if (index == 0) {
+ /*
+ * The timer event occurred. Check for timeout.
+ */
+ --timeout;
+ if (!timeout) {
+ efi_st_error("Timeout occurred\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Send further DHCP discover message
+ */
+ ret = send_dhcp_discover();
+ if (ret != EFI_SUCCESS)
+ return EFI_ST_FAILURE;
+ continue;
+ }
+ /*
+ * Receive packet
+ */
+ buffer_size = sizeof(buffer);
+ ret = net->get_status(net, &int_status, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to get status");
+ return EFI_ST_FAILURE;
+ }
+ if (!(int_status & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT)) {
+ efi_st_error("RX interrupt not set");
+ return EFI_ST_FAILURE;
+ }
+ ret = net->receive(net, NULL, &buffer_size, &buffer,
+ &srcaddr, &destaddr, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to receive packet");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Check the packet is meant for this system.
+ * Unfortunately QEMU ignores the broadcast flag.
+ * So we have to check for broadcasts too.
+ */
+ if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) &&
+ memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+ continue;
+ /*
+ * Check this is a DHCP reply
+ */
+ if (buffer.p.eth_hdr.et_protlen != ntohs(PROT_IP) ||
+ buffer.p.ip_udp.ip_hl_v != 0x45 ||
+ buffer.p.ip_udp.ip_p != IPPROTO_UDP ||
+ buffer.p.ip_udp.udp_src != ntohs(67) ||
+ buffer.p.ip_udp.udp_dst != ntohs(68) ||
+ buffer.p.dhcp_hdr.op != BOOTREPLY)
+ continue;
+ /*
+ * We successfully received a DHCP reply.
+ */
+ break;
+ }
+
+ /*
+ * Write a log message.
+ */
+ addr = (u8 *)&buffer.p.ip_udp.ip_src;
+ efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ",
+ addr[0], addr[1], addr[2], addr[3], &srcaddr);
+ if (!memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+ efi_st_printf("as broadcast message.\n");
+ else
+ efi_st_printf("as unicast message.\n");
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the timer event created in setup.
+ * Shut down the network adapter.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+ int exit_status = EFI_ST_SUCCESS;
+
+ if (timer) {
+ /*
+ * Stop timer.
+ */
+ ret = boottime->set_timer(timer, EFI_TIMER_STOP, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to stop timer");
+ exit_status = EFI_ST_FAILURE;
+ }
+ /*
+ * Close timer event.
+ */
+ ret = boottime->close_event(timer);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to close event");
+ exit_status = EFI_ST_FAILURE;
+ }
+ }
+ if (net) {
+ /*
+ * Shut down network adapter.
+ */
+ ret = net->shutdown(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to shut down network adapter\n");
+ exit_status = EFI_ST_FAILURE;
+ }
+ if (net->mode->state != EFI_NETWORK_STARTED) {
+ efi_st_error("Failed to shutdown network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ /*
+ * Stop network adapter.
+ */
+ ret = net->stop(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to stop network adapter\n");
+ exit_status = EFI_ST_FAILURE;
+ }
+ if (net->mode->state != EFI_NETWORK_STOPPED) {
+ efi_st_error("Failed to stop network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+
+ return exit_status;
+}
+
+EFI_UNIT_TEST(snp) = {
+ .name = "simple network protocol",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+#ifdef CONFIG_SANDBOX
+ /*
+ * Running this test on the sandbox requires setting environment
+ * variable ethact to a network interface connected to a DHCP server and
+ * ethrotate to 'no'.
+ */
+ .on_request = true,
+#endif
+};
diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c
new file mode 100644
index 00000000..11207b81
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_startimage_exit.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_start_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the StartImage boot service.
+ * The efi_selftest_miniapp_exit.efi application is loaded into memory
+ * and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image_exit.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ image_handle = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t r = EFI_ST_SUCCESS;
+
+ if (image) {
+ r = boottime->free_pool(image);
+ if (r != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return r;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+ efi_uintn_t exit_data_size = 0;
+ u16 *exit_data = NULL;
+ u16 expected_text[] = EFI_ST_SUCCESS_STR;
+
+ ret = boottime->load_image(false, image_handle, NULL, image,
+ img.length, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, &exit_data_size, &exit_data);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("Wrong return value from application\n");
+ return EFI_ST_FAILURE;
+ }
+ if (!exit_data || exit_data_size != sizeof(expected_text) ||
+ memcmp(exit_data, expected_text, sizeof(expected_text))) {
+ efi_st_error("Incorrect exit data\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->free_pool(exit_data);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to free exit data\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(startimage_exit) = {
+ .name = "start image exit",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_startimage_return.c b/lib/efi_selftest/efi_selftest_startimage_return.c
new file mode 100644
index 00000000..fabf53d9
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_startimage_return.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_start_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the StartImage boot service.
+ * The efi_selftest_miniapp_return.efi application is loaded into memory
+ * and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image_return.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+ (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ image_handle = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t r = EFI_ST_SUCCESS;
+
+ if (image) {
+ r = boottime->free_pool(image);
+ if (r != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return r;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ ret = boottime->load_image(false, image_handle, NULL, image,
+ img.length, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, NULL, NULL);
+ if (ret != EFI_INCOMPATIBLE_VERSION) {
+ efi_st_error("Wrong return value from application\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(startimage) = {
+ .name = "start image return",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_textinput.c b/lib/efi_selftest/efi_selftest_textinput.c
new file mode 100644
index 00000000..b90671cd
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_textinput.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_textinput
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+ * The Unicode character and the scan code are printed for text
+ * input. To run the test:
+ *
+ * setenv efi_selftest text input
+ * bootefi selftest
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ struct efi_input_key input_key = {0};
+ efi_status_t ret;
+ efi_uintn_t index;
+
+ /* Drain the console input */
+ ret = con_in->reset(con_in, true);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Reset failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_in->read_key_stroke(con_in, &input_key);
+ if (ret != EFI_NOT_READY) {
+ efi_st_error("Empty buffer not reported\n");
+ return EFI_ST_FAILURE;
+ }
+
+ efi_st_printf("Waiting for your input\n");
+ efi_st_printf("To terminate type 'x'\n");
+
+ for (;;) {
+ /* Wait for next key */
+ ret = boottime->wait_for_event(1, &con_in->wait_for_key,
+ &index);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("WaitForEvent failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_in->read_key_stroke(con_in, &input_key);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ReadKeyStroke failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Allow 5 minutes until time out */
+ boottime->set_watchdog_timer(300, 0, 0, NULL);
+
+ efi_st_printf("Unicode char %u (%ps), scan code %u (%ps)\n",
+ (unsigned int)input_key.unicode_char,
+ efi_st_translate_char(input_key.unicode_char),
+ (unsigned int)input_key.scan_code,
+ efi_st_translate_code(input_key.scan_code));
+
+ switch (input_key.unicode_char) {
+ case 'x':
+ case 'X':
+ return EFI_ST_SUCCESS;
+ }
+ }
+}
+
+EFI_UNIT_TEST(textinput) = {
+ .name = "text input",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .on_request = true,
+};
diff --git a/lib/efi_selftest/efi_selftest_textinputex.c b/lib/efi_selftest/efi_selftest_textinputex.c
new file mode 100644
index 00000000..de44224c
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_textinputex.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_textinput
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+ * The unicode character and the scan code are printed for text
+ * input. To run the test:
+ *
+ * setenv efi_selftest extended text input
+ * bootefi selftest
+ */
+
+#include <efi_selftest.h>
+
+static const efi_guid_t text_input_ex_protocol_guid =
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
+
+static struct efi_simple_text_input_ex_protocol *con_in_ex;
+
+static struct efi_boot_services *boottime;
+
+static void *efi_key_notify_handle;
+static bool efi_running;
+
+/**
+ * efi_key_notify_function() - key notification function
+ *
+ * This function is called when the registered key is hit.
+ *
+ * @key_data: next key
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_key_notify_function
+ (struct efi_key_data *key_data)
+{
+ efi_running = false;
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ struct efi_key_data key_data = {
+ .key = {
+ .scan_code = 0,
+ .unicode_char = 0x18
+ },
+ .key_state = {
+ .key_shift_state = EFI_SHIFT_STATE_VALID |
+ EFI_LEFT_CONTROL_PRESSED,
+ .key_toggle_state = EFI_TOGGLE_STATE_INVALID,
+ },
+ };
+
+ boottime = systable->boottime;
+
+ ret = boottime->locate_protocol(&text_input_ex_protocol_guid, NULL,
+ (void **)&con_in_ex);
+ if (ret != EFI_SUCCESS) {
+ con_in_ex = NULL;
+ efi_st_error
+ ("Extended text input protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = con_in_ex->register_key_notify(con_in_ex, &key_data,
+ efi_key_notify_function,
+ &efi_key_notify_handle);
+ if (ret != EFI_SUCCESS) {
+ efi_key_notify_handle = NULL;
+ efi_st_error
+ ("Notify function could not be registered.\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_running = true;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Unregister notify function.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ ret = con_in_ex->unregister_key_notify
+ (con_in_ex, efi_key_notify_handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error
+ ("Notify function could not be registered.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ struct efi_key_data input_key = { {0, 0}, {0, 0} };
+ efi_status_t ret;
+ efi_uintn_t index;
+
+ if (!con_in_ex) {
+ efi_st_printf("Setup failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Drain the console input */
+ ret = con_in_ex->reset(con_in_ex, true);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Reset failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
+ if (ret != EFI_NOT_READY) {
+ efi_st_error("Empty buffer not reported\n");
+ return EFI_ST_FAILURE;
+ }
+
+ efi_st_printf("Waiting for your input\n");
+ efi_st_printf("To terminate type 'CTRL+x'\n");
+
+ while (efi_running) {
+ /* Wait for next key */
+ ret = boottime->wait_for_event(1, &con_in_ex->wait_for_key_ex,
+ &index);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("WaitForEvent failed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("ReadKeyStroke failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Allow 5 minutes until time out */
+ boottime->set_watchdog_timer(300, 0, 0, NULL);
+
+ efi_st_printf("Unicode char %u (%ps), scan code %u (",
+ (unsigned int)input_key.key.unicode_char,
+ efi_st_translate_char(input_key.key.unicode_char),
+ (unsigned int)input_key.key.scan_code);
+ if (input_key.key_state.key_shift_state &
+ EFI_SHIFT_STATE_VALID) {
+ if (input_key.key_state.key_shift_state &
+ (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED))
+ efi_st_printf("SHIFT+");
+ if (input_key.key_state.key_shift_state &
+ (EFI_LEFT_ALT_PRESSED | EFI_RIGHT_ALT_PRESSED))
+ efi_st_printf("ALT+");
+ if (input_key.key_state.key_shift_state &
+ (EFI_LEFT_CONTROL_PRESSED |
+ EFI_RIGHT_CONTROL_PRESSED))
+ efi_st_printf("CTRL+");
+ if (input_key.key_state.key_shift_state &
+ (EFI_LEFT_LOGO_PRESSED | EFI_RIGHT_LOGO_PRESSED))
+ efi_st_printf("META+");
+ if (input_key.key_state.key_shift_state ==
+ EFI_SHIFT_STATE_VALID)
+ efi_st_printf("+");
+ }
+
+ efi_st_printf("%ps)\n",
+ efi_st_translate_code(input_key.key.scan_code));
+
+ }
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(textinputex) = {
+ .name = "extended text input",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+ .on_request = true,
+};
diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c
new file mode 100644
index 00000000..a87f65e1
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_textoutput.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_textoutput
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
+ *
+ * The following services are tested:
+ * OutputString, TestString, SetAttribute.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ size_t foreground;
+ size_t background;
+ size_t attrib;
+ efi_status_t ret;
+ s16 col;
+ u16 cr[] = { 0x0d, 0x00 };
+ u16 lf[] = { 0x0a, 0x00 };
+ u16 brahmi[] = { /* 2 Brahmi letters */
+ 0xD804, 0xDC05,
+ 0xD804, 0xDC22,
+ 0};
+
+ /* SetAttribute */
+ efi_st_printf("\nColor palette\n");
+ for (foreground = 0; foreground < 0x10; ++foreground) {
+ for (background = 0; background < 0x80; background += 0x10) {
+ attrib = foreground | background;
+ con_out->set_attribute(con_out, attrib);
+ efi_st_printf("%p", (void *)attrib);
+ }
+ con_out->set_attribute(con_out, 0);
+ efi_st_printf("\n");
+ }
+ /* TestString */
+ ret = con_out->test_string(con_out,
+ L" !\"#$%&'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~\n");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("TestString failed for ANSI characters\n");
+ return EFI_ST_FAILURE;
+ }
+ /* OutputString */
+ ret = con_out->output_string(con_out,
+ L"Testing cursor column update\n");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for ANSI characters");
+ return EFI_ST_FAILURE;
+ }
+ col = con_out->mode->cursor_column;
+ ret = con_out->output_string(con_out, lf);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for line feed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column != col) {
+ efi_st_error("Cursor column changed by line feed\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, cr);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for carriage return\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column) {
+ efi_st_error("Cursor column not 0 at beginning of line\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, L"123");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for ANSI characters\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column != 3) {
+ efi_st_error("Cursor column not incremented properly\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, L"\b");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for backspace\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column != 2) {
+ efi_st_error("Cursor column not decremented properly\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, L"\b\b");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for backspace\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column) {
+ efi_st_error("Cursor column not decremented properly\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, L"\b\b");
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_error("OutputString failed for backspace\n");
+ return EFI_ST_FAILURE;
+ }
+ if (con_out->mode->cursor_column) {
+ efi_st_error("Cursor column decremented past zero\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = con_out->output_string(con_out, brahmi);
+ if (ret != EFI_ST_SUCCESS) {
+ efi_st_todo("Unicode output not fully supported\n");
+ } else if (con_out->mode->cursor_column != 2) {
+ efi_st_printf("Unicode not handled properly\n");
+ return EFI_ST_FAILURE;
+ }
+ efi_st_printf("\n");
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(textoutput) = {
+ .name = "text output",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c
new file mode 100644
index 00000000..70a355ea
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_tpl.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_tpl
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test uses timer events to check the handling of
+ * task priority levels.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int notification_count;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments the notification count.
+ *
+ * @event notified event
+ * @context pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ unsigned int *count = context;
+
+ if (count)
+ ++*count;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK, notify,
+ (void *)&notification_count,
+ &event_notify);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+ TPL_HIGH_LEVEL, notify, NULL, &event_wait);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ if (event_notify) {
+ ret = boottime->close_event(event_notify);
+ event_notify = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (event_wait) {
+ ret = boottime->close_event(event_wait);
+ event_wait = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ boottime->restore_tpl(TPL_APPLICATION);
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Raise the TPL level to the level of the 10 ms timer and observe
+ * that the notification function is not called again.
+ *
+ * Lower the TPL level and check that the queued notification
+ * function is called.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_uintn_t index;
+ efi_status_t ret;
+ efi_uintn_t old_tpl;
+
+ /* Set 10 ms timer */
+ notification_count = 0;
+ ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 100 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ index = 5;
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->check_event(event_wait);
+ if (ret != EFI_NOT_READY) {
+ efi_st_error("Signaled state was not cleared.\n");
+ efi_st_printf("ret = %u\n", (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ if (index != 0) {
+ efi_st_error("WaitForEvent returned wrong index\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notification_count < 8 || notification_count > 12) {
+ efi_st_printf(
+ "Notification count with TPL level TPL_APPLICATION: %u\n",
+ notification_count);
+ efi_st_error("Incorrect timing of events\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not cancel timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Raise TPL level */
+ old_tpl = boottime->raise_tpl(TPL_CALLBACK);
+ if (old_tpl != TPL_APPLICATION) {
+ efi_st_error("Initial TPL level was not TPL_APPLICATION");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 10 ms timer */
+ notification_count = 0;
+ ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 100 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ do {
+ ret = boottime->check_event(event_wait);
+ } while (ret == EFI_NOT_READY);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not check event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notification_count != 0) {
+ efi_st_printf(
+ "Notification count with TPL level TPL_CALLBACK: %u\n",
+ notification_count);
+ efi_st_error("Suppressed timer fired\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set 1 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Restore the old TPL level */
+ boottime->restore_tpl(TPL_APPLICATION);
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notification_count < 1) {
+ efi_st_printf(
+ "Notification count with TPL level TPL_APPLICATION: %u\n",
+ notification_count);
+ efi_st_error("Queued timer event did not fire\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not cancel timer\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(tpl) = {
+ .name = "task priority levels",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_unaligned.c b/lib/efi_selftest/efi_selftest_unaligned.c
new file mode 100644
index 00000000..1802948e
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_unaligned.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_unaligned
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test unaligned memory access on ARMv7.
+ */
+
+#include <efi_selftest.h>
+
+struct aligned_buffer {
+ char a[8] __aligned(8);
+};
+
+/*
+ * Return an u32 at a give address.
+ * If the address is not four byte aligned, an unaligned memory access
+ * occurs.
+ *
+ * @addr: address to read
+ * @return: value at the address
+ */
+static inline u32 deref(u32 *addr)
+{
+ int ret;
+
+ asm(
+ "ldr %[out], [%[in]]\n\t"
+ : [out] "=r" (ret)
+ : [in] "r" (addr)
+ );
+ return ret;
+}
+
+/*
+ * Execute unit test.
+ * An unaligned memory access is executed. The result is checked.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ struct aligned_buffer buf = {
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ };
+ void *v = &buf;
+ u32 r = 0;
+
+ /* Read an unaligned address */
+ r = deref(v + 1);
+
+ /* UEFI only supports low endian systems */
+ if (r != 0x04030201) {
+ efi_st_error("Unaligned access failed");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(unaligned) = {
+ .name = "unaligned memory access",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_unicode_collation.c b/lib/efi_selftest/efi_selftest_unicode_collation.c
new file mode 100644
index 00000000..75294307
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_unicode_collation.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_unicode_collation
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test unicode collation protocol.
+ */
+
+#include <efi_selftest.h>
+
+static const efi_guid_t unicode_collation_protocol_guid =
+ EFI_UNICODE_COLLATION_PROTOCOL2_GUID;
+
+static struct efi_boot_services *boottime;
+
+static struct efi_unicode_collation_protocol *unicode_collation_protocol;
+
+/**
+ * setup() - setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * ReturnValue: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ ret = boottime->locate_protocol(&unicode_collation_protocol_guid, NULL,
+ (void **)&unicode_collation_protocol);
+ if (ret != EFI_SUCCESS) {
+ unicode_collation_protocol = NULL;
+ efi_st_error("Unicode collation protocol is not available.\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_stri_coll(void)
+{
+ efi_intn_t ret;
+ u16 c1[] = L"first";
+ u16 c2[] = L"FIRST";
+ u16 c3[] = L"second";
+
+ ret = unicode_collation_protocol->stri_coll(unicode_collation_protocol,
+ c1, c2);
+ if (ret) {
+ efi_st_error(
+ "stri_coll(\"%ps\", \"%ps\") = %d\n", c1, c2, (int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->stri_coll(unicode_collation_protocol,
+ c1, c3);
+ if (ret >= 0) {
+ efi_st_error(
+ "stri_coll(\"%ps\", \"%ps\") = %d\n", c1, c3, (int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->stri_coll(unicode_collation_protocol,
+ c3, c1);
+ if (ret <= 0) {
+ efi_st_error(
+ "stri_coll(\"%ps\", \"%ps\") = %d\n", c3, c1, (int)ret);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_metai_match(void)
+{
+ bool ret;
+ const u16 c[] = L"Das U-Boot";
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"*");
+ if (!ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da[rstu] U-Boot");
+ if (!ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da[q-v] U-Boot");
+ if (!ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da? U-Boot");
+ if (!ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"D*Bo*t");
+ if (!ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da[xyz] U-Boot");
+ if (ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da[a-d] U-Boot");
+ if (ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"Da?? U-Boot");
+ if (ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ ret = unicode_collation_protocol->metai_match(
+ unicode_collation_protocol, c, L"D*Bo*tt");
+ if (ret) {
+ efi_st_error("metai_match returned %u\n", ret);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_str_lwr(void)
+{
+ u16 c[] = L"U-Boot";
+
+ unicode_collation_protocol->str_lwr(unicode_collation_protocol, c);
+ if (efi_st_strcmp_16_8(c, "u-boot")) {
+ efi_st_error("str_lwr returned \"%ps\"\n", c);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_str_upr(void)
+{
+ u16 c[] = L"U-Boot";
+
+ unicode_collation_protocol->str_upr(unicode_collation_protocol, c);
+ if (efi_st_strcmp_16_8(c, "U-BOOT")) {
+ efi_st_error("str_lwr returned \"%ps\"\n", c);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_fat_to_str(void)
+{
+ u16 str[16];
+
+ boottime->set_mem(str, sizeof(str), 0);
+ unicode_collation_protocol->fat_to_str(unicode_collation_protocol, 6,
+ "U-BOOT", str);
+ if (efi_st_strcmp_16_8(str, "U-BOOT")) {
+ efi_st_error("fat_to_str returned \"%ps\"\n", str);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+static int test_str_to_fat(void)
+{
+ char fat[16];
+ bool ret;
+
+ boottime->set_mem(fat, sizeof(fat), 0);
+ ret = unicode_collation_protocol->str_to_fat(unicode_collation_protocol,
+ L"U -Boo.t", 6, fat);
+ if (ret || efi_st_strcmp_16_8(L"U-BOOT", fat)) {
+ efi_st_error("str_to_fat returned %u, \"%s\"\n", ret, fat);
+ return EFI_ST_FAILURE;
+ }
+
+ boottime->set_mem(fat, 16, 0);
+ ret = unicode_collation_protocol->str_to_fat(unicode_collation_protocol,
+ L"U\\Boot", 6, fat);
+ if (!ret || efi_st_strcmp_16_8(L"U_BOOT", fat)) {
+ efi_st_error("str_to_fat returned %u, \"%s\"\n", ret, fat);
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * execute() - Execute unit test.
+ *
+ * ReturnValue: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ int ret;
+
+ if (!unicode_collation_protocol) {
+ efi_st_printf("Unicode collation protocol missing\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = test_stri_coll();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ ret = test_metai_match();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ ret = test_str_lwr();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ ret = test_str_upr();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ ret = test_fat_to_str();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ ret = test_str_to_fat();
+ if (ret != EFI_ST_SUCCESS)
+ return ret;
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(unicoll) = {
+ .name = "unicode collation",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .execute = execute,
+ .setup = setup,
+};
diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c
new file mode 100644
index 00000000..ea73c252
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_util.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_util
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Utility functions
+ */
+
+#include <efi_selftest.h>
+
+struct efi_st_translate {
+ u16 code;
+ u16 *text;
+};
+
+static struct efi_st_translate efi_st_control_characters[] = {
+ {0, L"Null"},
+ {8, L"BS"},
+ {9, L"TAB"},
+ {10, L"LF"},
+ {13, L"CR"},
+ {0, NULL},
+};
+
+static u16 efi_st_ch[] = L"' '";
+static u16 efi_st_unknown[] = L"unknown";
+
+static struct efi_st_translate efi_st_scan_codes[] = {
+ {0x00, L"Null"},
+ {0x01, L"Up"},
+ {0x02, L"Down"},
+ {0x03, L"Right"},
+ {0x04, L"Left"},
+ {0x05, L"Home"},
+ {0x06, L"End"},
+ {0x07, L"Insert"},
+ {0x08, L"Delete"},
+ {0x09, L"Page Up"},
+ {0x0a, L"Page Down"},
+ {0x0b, L"FN 1"},
+ {0x0c, L"FN 2"},
+ {0x0d, L"FN 3"},
+ {0x0e, L"FN 4"},
+ {0x0f, L"FN 5"},
+ {0x10, L"FN 6"},
+ {0x11, L"FN 7"},
+ {0x12, L"FN 8"},
+ {0x13, L"FN 9"},
+ {0x14, L"FN 10"},
+ {0x15, L"FN 11"},
+ {0x16, L"FN 12"},
+ {0x17, L"Escape"},
+ {0x68, L"FN 13"},
+ {0x69, L"FN 14"},
+ {0x6a, L"FN 15"},
+ {0x6b, L"FN 16"},
+ {0x6c, L"FN 17"},
+ {0x6d, L"FN 18"},
+ {0x6e, L"FN 19"},
+ {0x6f, L"FN 20"},
+ {0x70, L"FN 21"},
+ {0x71, L"FN 22"},
+ {0x72, L"FN 23"},
+ {0x73, L"FN 24"},
+ {0x7f, L"Mute"},
+ {0x80, L"Volume Up"},
+ {0x81, L"Volume Down"},
+ {0x100, L"Brightness Up"},
+ {0x101, L"Brightness Down"},
+ {0x102, L"Suspend"},
+ {0x103, L"Hibernate"},
+ {0x104, L"Toggle Display"},
+ {0x105, L"Recovery"},
+ {0x106, L"Reject"},
+ {0x0, NULL},
+};
+
+u16 *efi_st_translate_char(u16 code)
+{
+ struct efi_st_translate *tr;
+
+ if (code >= ' ') {
+ efi_st_ch[1] = code;
+ return efi_st_ch;
+ }
+ for (tr = efi_st_control_characters; tr->text; ++tr) {
+ if (tr->code == code)
+ return tr->text;
+ }
+ return efi_st_unknown;
+}
+
+u16 *efi_st_translate_code(u16 code)
+{
+ struct efi_st_translate *tr;
+
+ for (tr = efi_st_scan_codes; tr->text; ++tr) {
+ if (tr->code == code)
+ return tr->text;
+ }
+ return efi_st_unknown;
+}
+
+int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
+{
+ for (; *buf1 || *buf2; ++buf1, ++buf2) {
+ if (*buf1 != *buf2)
+ return *buf1 - *buf2;
+ }
+ return 0;
+}
diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c
new file mode 100644
index 00000000..5d98c029
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_variables.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_variables
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the runtime services for variables:
+ * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_MAX_DATA_SIZE 16
+#define EFI_ST_MAX_VARNAME_SIZE 40
+
+static struct efi_boot_services *boottime;
+static struct efi_runtime_services *runtime;
+static const efi_guid_t guid_vendor0 =
+ EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1,
+ 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6);
+static const efi_guid_t guid_vendor1 =
+ EFI_GUID(0xff629290, 0x1fc1, 0xd73f,
+ 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea);
+
+/*
+ * Setup unit test.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+ runtime = systable->runtime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t len;
+ u32 attr;
+ u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c,
+ 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,};
+ u8 data[EFI_ST_MAX_DATA_SIZE];
+ u16 varname[EFI_ST_MAX_VARNAME_SIZE];
+ int flag;
+ efi_guid_t guid;
+ u64 max_storage, rem_storage, max_size;
+
+ ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ &max_storage, &rem_storage,
+ &max_size);
+ if (ret != EFI_SUCCESS) {
+ efi_st_todo("QueryVariableInfo failed\n");
+ } else if (!max_storage || !rem_storage || !max_size) {
+ efi_st_error("QueryVariableInfo: wrong info\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set variable 0 */
+ ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 3, v + 4);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ data[3] = 0xff;
+ len = 3;
+ ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
+ &attr, &len, data);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(data, v + 4, 3)) {
+ efi_st_error("GetVariable returned wrong value\n");
+ return EFI_ST_FAILURE;
+ }
+ if (data[3] != 0xff) {
+ efi_st_error("GetVariable wrote past the end of the buffer\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Set variable 1 */
+ ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 8, v);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = EFI_ST_MAX_DATA_SIZE;
+ ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
+ &attr, &len, data);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (len != 8) {
+ efi_st_error("GetVariable returned wrong length %u\n",
+ (unsigned int)len);
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(data, v, 8)) {
+ efi_st_error("GetVariable returned wrong value\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Append variable 1 */
+ ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_APPEND_WRITE,
+ 7, v + 8);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVariable(APPEND_WRITE) failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = EFI_ST_MAX_DATA_SIZE;
+ ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
+ &attr, &len, data);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (len != 15)
+ efi_st_todo("GetVariable returned wrong length %u\n",
+ (unsigned int)len);
+ if (memcmp(data, v, len))
+ efi_st_todo("GetVariable returned wrong value\n");
+ /* Append variable 2 */
+ ret = runtime->set_variable(L"efi_none", &guid_vendor1,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_APPEND_WRITE,
+ 15, v);
+ if (ret != EFI_NOT_FOUND) {
+ efi_st_error("SetVariable(APPEND_WRITE) with size 0 to non-existent variable returns wrong code\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Enumerate variables */
+ boottime->set_mem(&guid, 16, 0);
+ *varname = 0;
+ flag = 0;
+ for (;;) {
+ len = EFI_ST_MAX_VARNAME_SIZE;
+ ret = runtime->get_next_variable_name(&len, varname, &guid);
+ if (ret == EFI_NOT_FOUND)
+ break;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("GetNextVariableName failed (%u)\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ if (!memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
+ !efi_st_strcmp_16_8(varname, "efi_st_var0"))
+ flag |= 1;
+ if (!memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
+ !efi_st_strcmp_16_8(varname, "efi_st_var1"))
+ flag |= 2;
+ }
+ if (flag != 3) {
+ efi_st_error(
+ "GetNextVariableName did not return all variables\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Delete variable 1 */
+ ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
+ 0, 0, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = EFI_ST_MAX_DATA_SIZE;
+ ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
+ &attr, &len, data);
+ if (ret != EFI_NOT_FOUND) {
+ efi_st_error("Variable was not deleted\n");
+ return EFI_ST_FAILURE;
+ }
+ /* Delete variable 0 */
+ ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
+ 0, 0, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = EFI_ST_MAX_DATA_SIZE;
+ ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
+ &attr, &len, data);
+ if (ret != EFI_NOT_FOUND) {
+ efi_st_error("Variable was not deleted\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(variables) = {
+ .name = "variables",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_variables_runtime.c b/lib/efi_selftest/efi_selftest_variables_runtime.c
new file mode 100644
index 00000000..b3b40ad2
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_variables_runtime.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_variables_runtime
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the runtime services for variables after
+ * ExitBootServices():
+ * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_MAX_DATA_SIZE 16
+#define EFI_ST_MAX_VARNAME_SIZE 40
+
+static struct efi_boot_services *boottime;
+static struct efi_runtime_services *runtime;
+static const efi_guid_t guid_vendor0 =
+ EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1,
+ 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6);
+
+/*
+ * Setup unit test.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+ runtime = systable->runtime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * execute() - execute unit test
+ *
+ * As runtime support is not implmented expect EFI_UNSUPPORTED to be returned.
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t len;
+ u32 attr;
+ u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c,
+ 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,};
+ u8 data[EFI_ST_MAX_DATA_SIZE];
+ u16 varname[EFI_ST_MAX_VARNAME_SIZE];
+ efi_guid_t guid;
+ u64 max_storage, rem_storage, max_size;
+
+ ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ &max_storage, &rem_storage,
+ &max_size);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("QueryVariableInfo failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 3, v + 4);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = 3;
+ ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
+ &attr, &len, data);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("GetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ memset(&guid, 0, 16);
+ *varname = 0;
+ ret = runtime->get_next_variable_name(&len, varname, &guid);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("GetNextVariableName failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(variables_run) = {
+ .name = "variables at runtime",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_watchdog.c b/lib/efi_selftest/efi_selftest_watchdog.c
new file mode 100644
index 00000000..cbc67617
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_watchdog.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_watchdog
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * The 'watchdog timer' unit test checks that the watchdog timer
+ * will not cause a system restart during the timeout period after
+ * a timer reset.
+ *
+ * The 'watchdog reboot' unit test checks that the watchdog timer
+ * actually reboots the system after a timeout. The test is only
+ * executed on explicit request. Use the following commands:
+ *
+ * setenv efi_selftest watchdog reboot
+ * bootefi selftest
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * This is the communication structure for the notification function.
+ */
+struct notify_context {
+ /* Status code returned when resetting watchdog */
+ efi_status_t status;
+ /* Number of invocations of the notification function */
+ unsigned int timer_ticks;
+};
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static struct efi_boot_services *boottime;
+static struct notify_context notification_context;
+static bool watchdog_reset;
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event notified event
+ * @context pointer to the timeout
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+ struct notify_context *notify_context = context;
+ efi_status_t ret = EFI_SUCCESS;
+
+ if (!notify_context)
+ return;
+
+ /* Reset watchdog timer to one second */
+ ret = boottime->set_watchdog_timer(1, 0, 0, NULL);
+ if (ret != EFI_SUCCESS)
+ notify_context->status = ret;
+ /* Count number of calls */
+ notify_context->timer_ticks++;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+
+ boottime = systable->boottime;
+
+ notification_context.status = EFI_SUCCESS;
+ notification_context.timer_ticks = 0;
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK, notify,
+ (void *)&notification_context,
+ &event_notify);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+ TPL_CALLBACK, notify, NULL, &event_wait);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("could not create event\n");
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute the test resetting the watchdog in a timely manner. No reboot occurs.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup_timer(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ watchdog_reset = true;
+ return setup(handle, systable);
+}
+
+/*
+ * Execute the test without resetting the watchdog. A system reboot occurs.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup_reboot(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ watchdog_reset = false;
+ return setup(handle, systable);
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret;
+
+ /* Set the watchdog timer to the five minute default value */
+ ret = boottime->set_watchdog_timer(300, 0, 0, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Setting watchdog timer failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (event_notify) {
+ ret = boottime->close_event(event_notify);
+ event_notify = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (event_wait) {
+ ret = boottime->close_event(event_wait);
+ event_wait = NULL;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not close event\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 600 ms periodic timer that resets the watchdog to one second
+ * on every timer tick.
+ *
+ * Run a 1350 ms single shot timer and check that the 600ms timer has
+ * been called 2 times.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ size_t index;
+ efi_status_t ret;
+
+ /* Set the watchdog timeout to one second */
+ ret = boottime->set_watchdog_timer(1, 0, 0, NULL);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Setting watchdog timer failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (watchdog_reset) {
+ /* Set 600 ms timer */
+ ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC,
+ 6000000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ /* Set 1350 ms timer */
+ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 13500000);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not set timer\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = boottime->wait_for_event(1, &event_wait, &index);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Could not wait for event\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notification_context.status != EFI_SUCCESS) {
+ efi_st_error("Setting watchdog timer failed\n");
+ return EFI_ST_FAILURE;
+ }
+ if (notification_context.timer_ticks != 2) {
+ efi_st_error("The timer was called %u times, expected 2.\n",
+ notification_context.timer_ticks);
+ return EFI_ST_FAILURE;
+ }
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(watchdog1) = {
+ .name = "watchdog timer",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup_timer,
+ .execute = execute,
+ .teardown = teardown,
+};
+
+EFI_UNIT_TEST(watchdog2) = {
+ .name = "watchdog reboot",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup_reboot,
+ .execute = execute,
+ .teardown = teardown,
+ .on_request = true,
+};
diff --git a/lib/errno.c b/lib/errno.c
new file mode 100644
index 00000000..8330a8fd
--- /dev/null
+++ b/lib/errno.c
@@ -0,0 +1 @@
+int errno = 0;
diff --git a/lib/errno_str.c b/lib/errno_str.c
new file mode 100644
index 00000000..2e5f4a88
--- /dev/null
+++ b/lib/errno_str.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ *
+ * SDPX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <errno.h>
+
+#define ERRNO_MSG(errno, msg) msg
+#define SAME_AS(x) (const char *)&errno_message[x]
+
+static const char * const errno_message[] = {
+ ERRNO_MSG(0, "Success"),
+ ERRNO_MSG(EPERM, "Operation not permitted"),
+ ERRNO_MSG(ENOENT, "No such file or directory"),
+ ERRNO_MSG(ESRCH, "No such process"),
+ ERRNO_MSG(EINTR, "Interrupted system call"),
+ ERRNO_MSG(EIO, "I/O error"),
+ ERRNO_MSG(ENXIO, "No such device or address"),
+ ERRNO_MSG(E2BIG, "Argument list too long"),
+ ERRNO_MSG(ENOEXEC, "Exec format error"),
+ ERRNO_MSG(EBADF, "Bad file number"),
+ ERRNO_MSG(ECHILD, "No child processes"),
+ ERRNO_MSG(EAGAIN, "Try again"),
+ ERRNO_MSG(ENOMEM, "Out of memory"),
+ ERRNO_MSG(EACCES, "Permission denied"),
+ ERRNO_MSG(EFAULT, "Bad address"),
+ ERRNO_MSG(ENOTBLK, "Block device required"),
+ ERRNO_MSG(EBUSY, "Device or resource busy"),
+ ERRNO_MSG(EEXIST, "File exists"),
+ ERRNO_MSG(EXDEV, "Cross-device link"),
+ ERRNO_MSG(ENODEV, "No such device"),
+ ERRNO_MSG(ENOTDIR, "Not a directory"),
+ ERRNO_MSG(EISDIR, "Is a directory"),
+ ERRNO_MSG(EINVAL, "Invalid argument"),
+ ERRNO_MSG(ENFILE, "File table overflow"),
+ ERRNO_MSG(EMFILE, "Too many open files"),
+ ERRNO_MSG(ENOTTY, "Not a typewriter"),
+ ERRNO_MSG(ETXTBSY, "Text file busy"),
+ ERRNO_MSG(EFBIG, "File too large"),
+ ERRNO_MSG(ENOSPC, "No space left on device"),
+ ERRNO_MSG(ESPIPE, "Illegal seek"),
+ ERRNO_MSG(EROFS, "Read-only file system"),
+ ERRNO_MSG(EMLINK, "Too many links"),
+ ERRNO_MSG(EPIPE, "Broken pipe"),
+ ERRNO_MSG(EDOM, "Math argument out of domain of func"),
+ ERRNO_MSG(ERANGE, "Math result not representable"),
+ ERRNO_MSG(EDEADLK, "Resource deadlock would occur"),
+ ERRNO_MSG(ENAMETOOLONG, "File name too long"),
+ ERRNO_MSG(ENOLCK, "No record locks available"),
+ ERRNO_MSG(ENOSYS, "Function not implemented"),
+ ERRNO_MSG(ENOTEMPTY, "Directory not empty"),
+ ERRNO_MSG(ELOOP, "Too many symbolic links encountered"),
+ ERRNO_MSG(EWOULDBLOCK, SAME_AS(EAGAIN)),
+ ERRNO_MSG(ENOMSG, "No message of desired type"),
+ ERRNO_MSG(EIDRM, "Identifier removed"),
+ ERRNO_MSG(ECHRNG, "Channel number out of range"),
+ ERRNO_MSG(EL2NSYNC, "Level 2 not synchronized"),
+ ERRNO_MSG(EL3HLT, "Level 3 halted"),
+ ERRNO_MSG(EL3RST, "Level 3 reset"),
+ ERRNO_MSG(ELNRNG, "Link number out of range"),
+ ERRNO_MSG(EUNATCH, "Protocol driver not attached"),
+ ERRNO_MSG(ENOCSI, "No CSI structure available"),
+ ERRNO_MSG(EL2HLT, "Level 2 halted"),
+ ERRNO_MSG(EBADE, "Invalid exchange"),
+ ERRNO_MSG(EBADR, "Invalid request descriptor"),
+ ERRNO_MSG(EXFULL, "Exchange full"),
+ ERRNO_MSG(ENOANO, "No anode"),
+ ERRNO_MSG(EBADRQC, "Invalid request code"),
+ ERRNO_MSG(EBADSLT, "Invalid slot"),
+ ERRNO_MSG(EDEADLOCK, SAME_AS(EDEADLK)),
+ ERRNO_MSG(EBFONT, "Bad font file format"),
+ ERRNO_MSG(ENOSTR, "Device not a stream"),
+ ERRNO_MSG(ENODATA, "No data available"),
+ ERRNO_MSG(ETIME, "Timer expired"),
+ ERRNO_MSG(ENOSR, "Out of streams resources"),
+ ERRNO_MSG(ENONET, "Machine is not on the network"),
+ ERRNO_MSG(ENOPKG, "Package not installed"),
+ ERRNO_MSG(EREMOTE, "Object is remote"),
+ ERRNO_MSG(ENOLINK, "Link has been severed"),
+ ERRNO_MSG(EADV, "Advertise error"),
+ ERRNO_MSG(ESRMNT, "Srmount error"),
+ ERRNO_MSG(ECOMM, "Communication error on send"),
+ ERRNO_MSG(EPROTO, "Protocol error"),
+ ERRNO_MSG(EMULTIHOP, "Multihop attempted"),
+ ERRNO_MSG(EDOTDOT, "RFS specific error"),
+ ERRNO_MSG(EBADMSG, "Not a data message"),
+ ERRNO_MSG(EOVERFLOW, "Value too large for defined data type"),
+ ERRNO_MSG(ENOTUNIQ, "Name not unique on network"),
+ ERRNO_MSG(EBADFD, "File descriptor in bad state"),
+ ERRNO_MSG(EREMCHG, "Remote address changed"),
+ ERRNO_MSG(ELIBACC, "Can not access a needed shared library"),
+ ERRNO_MSG(ELIBBAD, "Accessing a corrupted shared library"),
+ ERRNO_MSG(ELIBSCN, ".lib section in a.out corrupted"),
+ ERRNO_MSG(ELIBMAX, "Attempting to link in too many shared libraries"),
+ ERRNO_MSG(ELIBEXEC, "Cannot exec a shared library directly"),
+ ERRNO_MSG(EILSEQ, "Illegal byte sequence"),
+ ERRNO_MSG(ERESTART, "Interrupted system call should be restarted"),
+ ERRNO_MSG(ESTRPIPE, "Streams pipe error"),
+ ERRNO_MSG(EUSERS, "Too many users"),
+ ERRNO_MSG(ENOTSOCK, "Socket operation on non-socket"),
+ ERRNO_MSG(EDESTADDRREQ, "Destination address required"),
+ ERRNO_MSG(EMSGSIZE, "Message too long"),
+ ERRNO_MSG(EPROTOTYPE, "Protocol wrong type for socket"),
+ ERRNO_MSG(ENOPROTOOPT, "Protocol not available"),
+ ERRNO_MSG(EPROTONOSUPPORT, "Protocol not supported"),
+ ERRNO_MSG(ESOCKTNOSUPPORT, "Socket type not supported"),
+ ERRNO_MSG(EOPNOTSUPP, "Operation not supported on transport endpoint"),
+ ERRNO_MSG(EPFNOSUPPORT, "Protocol family not supported"),
+ ERRNO_MSG(AFNOSUPPORT, "Address family not supported by protocol"),
+ ERRNO_MSG(EADDRINUSE, "Address already in use"),
+ ERRNO_MSG(EADDRNOTAVAIL, "Cannot assign requested address"),
+ ERRNO_MSG(ENETDOWN, "Network is down"),
+ ERRNO_MSG(ENETUNREACH, "Network is unreachable"),
+ ERRNO_MSG(ENETRESET, "Network dropped connection because of reset"),
+ ERRNO_MSG(ECONNABORTED, "Software caused connection abort"),
+ ERRNO_MSG(ECONNRESET, "Connection reset by peer"),
+ ERRNO_MSG(ENOBUFS, "No buffer space available"),
+ ERRNO_MSG(EISCONN, "Transport endpoint is already connected"),
+ ERRNO_MSG(ENOTCONN, "Transport endpoint is not connected"),
+ ERRNO_MSG(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
+ ERRNO_MSG(ETOOMANYREFS, "Too many references: cannot splice"),
+ ERRNO_MSG(ETIMEDOUT, "Connection timed out"),
+ ERRNO_MSG(ECONNREFUSED, "Connection refused"),
+ ERRNO_MSG(EHOSTDOWN, "Host is down"),
+ ERRNO_MSG(EHOSTUNREACH, "No route to host"),
+ ERRNO_MSG(EALREADY, "Operation already in progress"),
+ ERRNO_MSG(EINPROGRESS, "Operation now in progress"),
+ ERRNO_MSG(ESTALE, "Stale NFS file handle"),
+ ERRNO_MSG(EUCLEAN, "Structure needs cleaning"),
+ ERRNO_MSG(ENOTNAM, "Not a XENIX named type file"),
+ ERRNO_MSG(ENAVAIL, "No XENIX semaphores available"),
+ ERRNO_MSG(EISNAM, "Is a named type file"),
+ ERRNO_MSG(EREMOTEIO, "Remote I/O error"),
+ ERRNO_MSG(EDQUOT, "Quota exceeded"),
+ ERRNO_MSG(ENOMEDIUM, "No medium found"),
+ ERRNO_MSG(EMEDIUMTYPE, "Wrong medium type"),
+ /* Message for unsupported error numbers */
+ ERRNO_MSG(0, "Unknown error"),
+};
+
+const char *errno_str(int errno)
+{
+ if (errno >= 0)
+ return errno_message[0];
+
+ errno = -errno;
+ if (errno >= ARRAY_SIZE(errno_message))
+ errno = ARRAY_SIZE(errno_message) - 1;
+
+ return errno_message[errno];
+}
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
new file mode 100644
index 00000000..61af3472
--- /dev/null
+++ b/lib/fdtdec.c
@@ -0,0 +1,1668 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <boot_fit.h>
+#include <dm.h>
+#include <dm/of_extra.h>
+#include <env.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <gzip.h>
+#include <mapmem.h>
+#include <linux/libfdt.h>
+#include <serial.h>
+#include <asm/sections.h>
+#include <linux/ctype.h>
+#include <linux/lzo.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Here are the type we know about. One day we might allow drivers to
+ * register. For now we just put them here. The COMPAT macro allows us to
+ * turn this into a sparse list later, and keeps the ID with the name.
+ *
+ * NOTE: This list is basically a TODO list for things that need to be
+ * converted to driver model. So don't add new things here unless there is a
+ * good reason why driver-model conversion is infeasible. Examples include
+ * things which are used before driver model is available.
+ */
+#define COMPAT(id, name) name
+static const char * const compat_names[COMPAT_COUNT] = {
+ COMPAT(UNKNOWN, "<none>"),
+ COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
+ COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
+ COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
+ COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
+ COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"),
+ COMPAT(SMSC_LAN9215, "smsc,lan9215"),
+ COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
+ COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
+ COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"),
+ COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
+ COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
+ COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"),
+ COMPAT(GENERIC_SPI_FLASH, "jedec,spi-nor"),
+ COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
+ COMPAT(INTEL_MICROCODE, "intel,microcode"),
+ COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+ COMPAT(ALTERA_SOCFPGA_DWMAC, "altr,socfpga-stmmac"),
+ COMPAT(ALTERA_SOCFPGA_DWMMC, "altr,socfpga-dw-mshc"),
+ COMPAT(ALTERA_SOCFPGA_DWC2USB, "snps,dwc2"),
+ COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
+ COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
+ COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
+ COMPAT(COMPAT_SUNXI_NAND, "allwinner,sun4i-a10-nand"),
+ COMPAT(ALTERA_SOCFPGA_CLK, "altr,clk-mgr"),
+ COMPAT(ALTERA_SOCFPGA_PINCTRL_SINGLE, "pinctrl-single"),
+ COMPAT(ALTERA_SOCFPGA_H2F_BRG, "altr,socfpga-hps2fpga-bridge"),
+ COMPAT(ALTERA_SOCFPGA_LWH2F_BRG, "altr,socfpga-lwhps2fpga-bridge"),
+ COMPAT(ALTERA_SOCFPGA_F2H_BRG, "altr,socfpga-fpga2hps-bridge"),
+ COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
+ COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
+ COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
+ COMPAT(ALTERA_SOCFPGA_FPGA0, "altr,socfpga-a10-fpga-mgr"),
+ COMPAT(ALTERA_SOCFPGA_NOC, "altr,socfpga-a10-noc"),
+ COMPAT(ALTERA_SOCFPGA_CLK_INIT, "altr,socfpga-a10-clk-init")
+};
+
+const char *fdtdec_get_compatible(enum fdt_compat_id id)
+{
+ /* We allow reading of the 'unknown' ID for testing purposes */
+ assert(id >= 0 && id < COMPAT_COUNT);
+ return compat_names[id];
+}
+
+fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
+ const char *prop_name, int index, int na,
+ int ns, fdt_size_t *sizep,
+ bool translate)
+{
+ const fdt32_t *prop, *prop_end;
+ const fdt32_t *prop_addr, *prop_size, *prop_after_size;
+ int len;
+ fdt_addr_t addr;
+
+ debug("%s: %s: ", __func__, prop_name);
+
+ prop = fdt_getprop(blob, node, prop_name, &len);
+ if (!prop) {
+ debug("(not found)\n");
+ return FDT_ADDR_T_NONE;
+ }
+ prop_end = prop + (len / sizeof(*prop));
+
+ prop_addr = prop + (index * (na + ns));
+ prop_size = prop_addr + na;
+ prop_after_size = prop_size + ns;
+ if (prop_after_size > prop_end) {
+ debug("(not enough data: expected >= %d cells, got %d cells)\n",
+ (u32)(prop_after_size - prop), ((u32)(prop_end - prop)));
+ return FDT_ADDR_T_NONE;
+ }
+
+#if CONFIG_IS_ENABLED(OF_TRANSLATE)
+ if (translate)
+ addr = fdt_translate_address(blob, node, prop_addr);
+ else
+#endif
+ addr = fdtdec_get_number(prop_addr, na);
+
+ if (sizep) {
+ *sizep = fdtdec_get_number(prop_size, ns);
+ debug("addr=%08llx, size=%llx\n", (unsigned long long)addr,
+ (unsigned long long)*sizep);
+ } else {
+ debug("addr=%08llx\n", (unsigned long long)addr);
+ }
+
+ return addr;
+}
+
+fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
+ int node, const char *prop_name,
+ int index, fdt_size_t *sizep,
+ bool translate)
+{
+ int na, ns;
+
+ debug("%s: ", __func__);
+
+ na = fdt_address_cells(blob, parent);
+ if (na < 1) {
+ debug("(bad #address-cells)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ ns = fdt_size_cells(blob, parent);
+ if (ns < 0) {
+ debug("(bad #size-cells)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ debug("na=%d, ns=%d, ", na, ns);
+
+ return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
+ ns, sizep, translate);
+}
+
+fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
+ const char *prop_name, int index,
+ fdt_size_t *sizep,
+ bool translate)
+{
+ int parent;
+
+ debug("%s: ", __func__);
+
+ parent = fdt_parent_offset(blob, node);
+ if (parent < 0) {
+ debug("(no parent found)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name,
+ index, sizep, translate);
+}
+
+fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
+ const char *prop_name, fdt_size_t *sizep)
+{
+ int ns = sizep ? (sizeof(fdt_size_t) / sizeof(fdt32_t)) : 0;
+
+ return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0,
+ sizeof(fdt_addr_t) / sizeof(fdt32_t),
+ ns, sizep, false);
+}
+
+fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name)
+{
+ return fdtdec_get_addr_size(blob, node, prop_name, NULL);
+}
+
+#if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI)
+int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
+{
+ const char *list, *end;
+ int len;
+
+ list = fdt_getprop(blob, node, "compatible", &len);
+ if (!list)
+ return -ENOENT;
+
+ end = list + len;
+ while (list < end) {
+ len = strlen(list);
+ if (len >= strlen("pciVVVV,DDDD")) {
+ char *s = strstr(list, "pci");
+
+ /*
+ * check if the string is something like pciVVVV,DDDD.RR
+ * or just pciVVVV,DDDD
+ */
+ if (s && s[7] == ',' &&
+ (s[12] == '.' || s[12] == 0)) {
+ s += 3;
+ *vendor = simple_strtol(s, NULL, 16);
+
+ s += 5;
+ *device = simple_strtol(s, NULL, 16);
+
+ return 0;
+ }
+ }
+ list += (len + 1);
+ }
+
+ return -ENOENT;
+}
+
+int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
+ u32 *bar)
+{
+ int barnum;
+
+ /* extract the bar number from fdt_pci_addr */
+ barnum = addr->phys_hi & 0xff;
+ if (barnum < PCI_BASE_ADDRESS_0 || barnum > PCI_CARDBUS_CIS)
+ return -EINVAL;
+
+ barnum = (barnum - PCI_BASE_ADDRESS_0) / 4;
+ *bar = dm_pci_read_bar32(dev, barnum);
+
+ return 0;
+}
+#endif
+
+uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
+ uint64_t default_val)
+{
+ const unaligned_fdt64_t *cell64;
+ int length;
+
+ cell64 = fdt_getprop(blob, node, prop_name, &length);
+ if (!cell64 || length < sizeof(*cell64))
+ return default_val;
+
+ return fdt64_to_cpu(*cell64);
+}
+
+int fdtdec_get_is_enabled(const void *blob, int node)
+{
+ const char *cell;
+
+ /*
+ * It should say "okay", so only allow that. Some fdts use "ok" but
+ * this is a bug. Please fix your device tree source file. See here
+ * for discussion:
+ *
+ * http://www.mail-archive.com/u-boot@lists.denx.de/msg71598.html
+ */
+ cell = fdt_getprop(blob, node, "status", NULL);
+ if (cell)
+ return strcmp(cell, "okay") == 0;
+ return 1;
+}
+
+enum fdt_compat_id fdtdec_lookup(const void *blob, int node)
+{
+ enum fdt_compat_id id;
+
+ /* Search our drivers */
+ for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++)
+ if (fdt_node_check_compatible(blob, node,
+ compat_names[id]) == 0)
+ return id;
+ return COMPAT_UNKNOWN;
+}
+
+int fdtdec_next_compatible(const void *blob, int node, enum fdt_compat_id id)
+{
+ return fdt_node_offset_by_compatible(blob, node, compat_names[id]);
+}
+
+int fdtdec_next_compatible_subnode(const void *blob, int node,
+ enum fdt_compat_id id, int *depthp)
+{
+ do {
+ node = fdt_next_node(blob, node, depthp);
+ } while (*depthp > 1);
+
+ /* If this is a direct subnode, and compatible, return it */
+ if (*depthp == 1 && 0 == fdt_node_check_compatible(
+ blob, node, compat_names[id]))
+ return node;
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdtdec_next_alias(const void *blob, const char *name, enum fdt_compat_id id,
+ int *upto)
+{
+#define MAX_STR_LEN 20
+ char str[MAX_STR_LEN + 20];
+ int node, err;
+
+ /* snprintf() is not available */
+ assert(strlen(name) < MAX_STR_LEN);
+ sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
+ node = fdt_path_offset(blob, str);
+ if (node < 0)
+ return node;
+ err = fdt_node_check_compatible(blob, node, compat_names[id]);
+ if (err < 0)
+ return err;
+ if (err)
+ return -FDT_ERR_NOTFOUND;
+ (*upto)++;
+ return node;
+}
+
+int fdtdec_find_aliases_for_id(const void *blob, const char *name,
+ enum fdt_compat_id id, int *node_list,
+ int maxcount)
+{
+ memset(node_list, '\0', sizeof(*node_list) * maxcount);
+
+ return fdtdec_add_aliases_for_id(blob, name, id, node_list, maxcount);
+}
+
+/* TODO: Can we tighten this code up a little? */
+int fdtdec_add_aliases_for_id(const void *blob, const char *name,
+ enum fdt_compat_id id, int *node_list,
+ int maxcount)
+{
+ int name_len = strlen(name);
+ int nodes[maxcount];
+ int num_found = 0;
+ int offset, node;
+ int alias_node;
+ int count;
+ int i, j;
+
+ /* find the alias node if present */
+ alias_node = fdt_path_offset(blob, "/aliases");
+
+ /*
+ * start with nothing, and we can assume that the root node can't
+ * match
+ */
+ memset(nodes, '\0', sizeof(nodes));
+
+ /* First find all the compatible nodes */
+ for (node = count = 0; node >= 0 && count < maxcount;) {
+ node = fdtdec_next_compatible(blob, node, id);
+ if (node >= 0)
+ nodes[count++] = node;
+ }
+ if (node >= 0)
+ debug("%s: warning: maxcount exceeded with alias '%s'\n",
+ __func__, name);
+
+ /* Now find all the aliases */
+ for (offset = fdt_first_property_offset(blob, alias_node);
+ offset > 0;
+ offset = fdt_next_property_offset(blob, offset)) {
+ const struct fdt_property *prop;
+ const char *path;
+ int number;
+ int found;
+
+ node = 0;
+ prop = fdt_get_property_by_offset(blob, offset, NULL);
+ path = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
+ if (prop->len && 0 == strncmp(path, name, name_len))
+ node = fdt_path_offset(blob, prop->data);
+ if (node <= 0)
+ continue;
+
+ /* Get the alias number */
+ number = simple_strtoul(path + name_len, NULL, 10);
+ if (number < 0 || number >= maxcount) {
+ debug("%s: warning: alias '%s' is out of range\n",
+ __func__, path);
+ continue;
+ }
+
+ /* Make sure the node we found is actually in our list! */
+ found = -1;
+ for (j = 0; j < count; j++)
+ if (nodes[j] == node) {
+ found = j;
+ break;
+ }
+
+ if (found == -1) {
+ debug("%s: warning: alias '%s' points to a node "
+ "'%s' that is missing or is not compatible "
+ " with '%s'\n", __func__, path,
+ fdt_get_name(blob, node, NULL),
+ compat_names[id]);
+ continue;
+ }
+
+ /*
+ * Add this node to our list in the right place, and mark
+ * it as done.
+ */
+ if (fdtdec_get_is_enabled(blob, node)) {
+ if (node_list[number]) {
+ debug("%s: warning: alias '%s' requires that "
+ "a node be placed in the list in a "
+ "position which is already filled by "
+ "node '%s'\n", __func__, path,
+ fdt_get_name(blob, node, NULL));
+ continue;
+ }
+ node_list[number] = node;
+ if (number >= num_found)
+ num_found = number + 1;
+ }
+ nodes[found] = 0;
+ }
+
+ /* Add any nodes not mentioned by an alias */
+ for (i = j = 0; i < maxcount; i++) {
+ if (!node_list[i]) {
+ for (; j < maxcount; j++)
+ if (nodes[j] &&
+ fdtdec_get_is_enabled(blob, nodes[j]))
+ break;
+
+ /* Have we run out of nodes to add? */
+ if (j == maxcount)
+ break;
+
+ assert(!node_list[i]);
+ node_list[i] = nodes[j++];
+ if (i >= num_found)
+ num_found = i + 1;
+ }
+ }
+
+ return num_found;
+}
+
+int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
+ int *seqp)
+{
+ int base_len = strlen(base);
+ const char *find_name;
+ int find_namelen;
+ int prop_offset;
+ int aliases;
+
+ find_name = fdt_get_name(blob, offset, &find_namelen);
+ debug("Looking for '%s' at %d, name %s\n", base, offset, find_name);
+
+ aliases = fdt_path_offset(blob, "/aliases");
+ for (prop_offset = fdt_first_property_offset(blob, aliases);
+ prop_offset > 0;
+ prop_offset = fdt_next_property_offset(blob, prop_offset)) {
+ const char *prop;
+ const char *name;
+ const char *slash;
+ int len, val;
+
+ prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
+ debug(" - %s, %s\n", name, prop);
+ if (len < find_namelen || *prop != '/' || prop[len - 1] ||
+ strncmp(name, base, base_len))
+ continue;
+
+ slash = strrchr(prop, '/');
+ if (strcmp(slash + 1, find_name))
+ continue;
+ val = trailing_strtol(name);
+ if (val != -1) {
+ *seqp = val;
+ debug("Found seq %d\n", *seqp);
+ return 0;
+ }
+ }
+
+ debug("Not found\n");
+ return -ENOENT;
+}
+
+int fdtdec_get_alias_highest_id(const void *blob, const char *base)
+{
+ int base_len = strlen(base);
+ int prop_offset;
+ int aliases;
+ int max = -1;
+
+ debug("Looking for highest alias id for '%s'\n", base);
+
+ aliases = fdt_path_offset(blob, "/aliases");
+ for (prop_offset = fdt_first_property_offset(blob, aliases);
+ prop_offset > 0;
+ prop_offset = fdt_next_property_offset(blob, prop_offset)) {
+ const char *prop;
+ const char *name;
+ int len, val;
+
+ prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
+ debug(" - %s, %s\n", name, prop);
+ if (*prop != '/' || prop[len - 1] ||
+ strncmp(name, base, base_len))
+ continue;
+
+ val = trailing_strtol(name);
+ if (val > max) {
+ debug("Found seq %d\n", val);
+ max = val;
+ }
+ }
+
+ return max;
+}
+
+const char *fdtdec_get_chosen_prop(const void *blob, const char *name)
+{
+ int chosen_node;
+
+ if (!blob)
+ return NULL;
+ chosen_node = fdt_path_offset(blob, "/chosen");
+ return fdt_getprop(blob, chosen_node, name, NULL);
+}
+
+int fdtdec_get_chosen_node(const void *blob, const char *name)
+{
+ const char *prop;
+
+ prop = fdtdec_get_chosen_prop(blob, name);
+ if (!prop)
+ return -FDT_ERR_NOTFOUND;
+ return fdt_path_offset(blob, prop);
+}
+
+int fdtdec_check_fdt(void)
+{
+ /*
+ * We must have an FDT, but we cannot panic() yet since the console
+ * is not ready. So for now, just assert(). Boards which need an early
+ * FDT (prior to console ready) will need to make their own
+ * arrangements and do their own checks.
+ */
+ assert(!fdtdec_prepare_fdt());
+ return 0;
+}
+
+/*
+ * This function is a little odd in that it accesses global data. At some
+ * point if the architecture board.c files merge this will make more sense.
+ * Even now, it is common code.
+ */
+int fdtdec_prepare_fdt(void)
+{
+ if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
+ fdt_check_header(gd->fdt_blob)) {
+#ifdef CONFIG_SPL_BUILD
+ puts("Missing DTB\n");
+#else
+ puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
+# ifdef DEBUG
+ if (gd->fdt_blob) {
+ printf("fdt_blob=%p\n", gd->fdt_blob);
+ print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4,
+ 32, 0);
+ }
+# endif
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name)
+{
+ const u32 *phandle;
+ int lookup;
+
+ debug("%s: %s\n", __func__, prop_name);
+ phandle = fdt_getprop(blob, node, prop_name, NULL);
+ if (!phandle)
+ return -FDT_ERR_NOTFOUND;
+
+ lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle));
+ return lookup;
+}
+
+/**
+ * Look up a property in a node and check that it has a minimum length.
+ *
+ * @param blob FDT blob
+ * @param node node to examine
+ * @param prop_name name of property to find
+ * @param min_len minimum property length in bytes
+ * @param err 0 if ok, or -FDT_ERR_NOTFOUND if the property is not
+ found, or -FDT_ERR_BADLAYOUT if not enough data
+ * @return pointer to cell, which is only valid if err == 0
+ */
+static const void *get_prop_check_min_len(const void *blob, int node,
+ const char *prop_name, int min_len,
+ int *err)
+{
+ const void *cell;
+ int len;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ if (!cell)
+ *err = -FDT_ERR_NOTFOUND;
+ else if (len < min_len)
+ *err = -FDT_ERR_BADLAYOUT;
+ else
+ *err = 0;
+ return cell;
+}
+
+int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
+ u32 *array, int count)
+{
+ const u32 *cell;
+ int err = 0;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = get_prop_check_min_len(blob, node, prop_name,
+ sizeof(u32) * count, &err);
+ if (!err) {
+ int i;
+
+ for (i = 0; i < count; i++)
+ array[i] = fdt32_to_cpu(cell[i]);
+ }
+ return err;
+}
+
+int fdtdec_get_int_array_count(const void *blob, int node,
+ const char *prop_name, u32 *array, int count)
+{
+ const u32 *cell;
+ int len, elems;
+ int i;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ if (!cell)
+ return -FDT_ERR_NOTFOUND;
+ elems = len / sizeof(u32);
+ if (count > elems)
+ count = elems;
+ for (i = 0; i < count; i++)
+ array[i] = fdt32_to_cpu(cell[i]);
+
+ return count;
+}
+
+const u32 *fdtdec_locate_array(const void *blob, int node,
+ const char *prop_name, int count)
+{
+ const u32 *cell;
+ int err;
+
+ cell = get_prop_check_min_len(blob, node, prop_name,
+ sizeof(u32) * count, &err);
+ return err ? NULL : cell;
+}
+
+int fdtdec_get_bool(const void *blob, int node, const char *prop_name)
+{
+ const s32 *cell;
+ int len;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ return cell != NULL;
+}
+
+int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
+ const char *list_name,
+ const char *cells_name,
+ int cell_count, int index,
+ struct fdtdec_phandle_args *out_args)
+{
+ const __be32 *list, *list_end;
+ int rc = 0, size, cur_index = 0;
+ uint32_t count = 0;
+ int node = -1;
+ int phandle;
+
+ /* Retrieve the phandle list property */
+ list = fdt_getprop(blob, src_node, list_name, &size);
+ if (!list)
+ return -ENOENT;
+ list_end = list + size / sizeof(*list);
+
+ /* Loop over the phandles until all the requested entry is found */
+ while (list < list_end) {
+ rc = -EINVAL;
+ count = 0;
+
+ /*
+ * If phandle is 0, then it is an empty entry with no
+ * arguments. Skip forward to the next entry.
+ */
+ phandle = be32_to_cpup(list++);
+ if (phandle) {
+ /*
+ * Find the provider node and parse the #*-cells
+ * property to determine the argument length.
+ *
+ * This is not needed if the cell count is hard-coded
+ * (i.e. cells_name not set, but cell_count is set),
+ * except when we're going to return the found node
+ * below.
+ */
+ if (cells_name || cur_index == index) {
+ node = fdt_node_offset_by_phandle(blob,
+ phandle);
+ if (!node) {
+ debug("%s: could not find phandle\n",
+ fdt_get_name(blob, src_node,
+ NULL));
+ goto err;
+ }
+ }
+
+ if (cells_name) {
+ count = fdtdec_get_int(blob, node, cells_name,
+ -1);
+ if (count == -1) {
+ debug("%s: could not get %s for %s\n",
+ fdt_get_name(blob, src_node,
+ NULL),
+ cells_name,
+ fdt_get_name(blob, node,
+ NULL));
+ goto err;
+ }
+ } else {
+ count = cell_count;
+ }
+
+ /*
+ * Make sure that the arguments actually fit in the
+ * remaining property data length
+ */
+ if (list + count > list_end) {
+ debug("%s: arguments longer than property\n",
+ fdt_get_name(blob, src_node, NULL));
+ goto err;
+ }
+ }
+
+ /*
+ * All of the error cases above bail out of the loop, so at
+ * this point, the parsing is successful. If the requested
+ * index matches, then fill the out_args structure and return,
+ * or return -ENOENT for an empty entry.
+ */
+ rc = -ENOENT;
+ if (cur_index == index) {
+ if (!phandle)
+ goto err;
+
+ if (out_args) {
+ int i;
+
+ if (count > MAX_PHANDLE_ARGS) {
+ debug("%s: too many arguments %d\n",
+ fdt_get_name(blob, src_node,
+ NULL), count);
+ count = MAX_PHANDLE_ARGS;
+ }
+ out_args->node = node;
+ out_args->args_count = count;
+ for (i = 0; i < count; i++) {
+ out_args->args[i] =
+ be32_to_cpup(list++);
+ }
+ }
+
+ /* Found it! return success */
+ return 0;
+ }
+
+ node = -1;
+ list += count;
+ cur_index++;
+ }
+
+ /*
+ * Result will be one of:
+ * -ENOENT : index is for empty phandle
+ * -EINVAL : parsing error on data
+ * [1..n] : Number of phandle (count mode; when index = -1)
+ */
+ rc = index < 0 ? cur_index : -ENOENT;
+ err:
+ return rc;
+}
+
+int fdtdec_get_child_count(const void *blob, int node)
+{
+ int subnode;
+ int num = 0;
+
+ fdt_for_each_subnode(subnode, blob, node)
+ num++;
+
+ return num;
+}
+
+int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
+ u8 *array, int count)
+{
+ const u8 *cell;
+ int err;
+
+ cell = get_prop_check_min_len(blob, node, prop_name, count, &err);
+ if (!err)
+ memcpy(array, cell, count);
+ return err;
+}
+
+const u8 *fdtdec_locate_byte_array(const void *blob, int node,
+ const char *prop_name, int count)
+{
+ const u8 *cell;
+ int err;
+
+ cell = get_prop_check_min_len(blob, node, prop_name, count, &err);
+ if (err)
+ return NULL;
+ return cell;
+}
+
+int fdtdec_get_config_int(const void *blob, const char *prop_name,
+ int default_val)
+{
+ int config_node;
+
+ debug("%s: %s\n", __func__, prop_name);
+ config_node = fdt_path_offset(blob, "/config");
+ if (config_node < 0)
+ return default_val;
+ return fdtdec_get_int(blob, config_node, prop_name, default_val);
+}
+
+int fdtdec_get_config_bool(const void *blob, const char *prop_name)
+{
+ int config_node;
+ const void *prop;
+
+ debug("%s: %s\n", __func__, prop_name);
+ config_node = fdt_path_offset(blob, "/config");
+ if (config_node < 0)
+ return 0;
+ prop = fdt_get_property(blob, config_node, prop_name, NULL);
+
+ return prop != NULL;
+}
+
+char *fdtdec_get_config_string(const void *blob, const char *prop_name)
+{
+ const char *nodep;
+ int nodeoffset;
+ int len;
+
+ debug("%s: %s\n", __func__, prop_name);
+ nodeoffset = fdt_path_offset(blob, "/config");
+ if (nodeoffset < 0)
+ return NULL;
+
+ nodep = fdt_getprop(blob, nodeoffset, prop_name, &len);
+ if (!nodep)
+ return NULL;
+
+ return (char *)nodep;
+}
+
+u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
+{
+ u64 number = 0;
+
+ while (cells--)
+ number = (number << 32) | fdt32_to_cpu(*ptr++);
+
+ return number;
+}
+
+int fdt_get_resource(const void *fdt, int node, const char *property,
+ unsigned int index, struct fdt_resource *res)
+{
+ const fdt32_t *ptr, *end;
+ int na, ns, len, parent;
+ unsigned int i = 0;
+
+ parent = fdt_parent_offset(fdt, node);
+ if (parent < 0)
+ return parent;
+
+ na = fdt_address_cells(fdt, parent);
+ ns = fdt_size_cells(fdt, parent);
+
+ ptr = fdt_getprop(fdt, node, property, &len);
+ if (!ptr)
+ return len;
+
+ end = ptr + len / sizeof(*ptr);
+
+ while (ptr + na + ns <= end) {
+ if (i == index) {
+ res->start = fdtdec_get_number(ptr, na);
+ res->end = res->start;
+ res->end += fdtdec_get_number(&ptr[na], ns) - 1;
+ return 0;
+ }
+
+ ptr += na + ns;
+ i++;
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+ const char *prop_names, const char *name,
+ struct fdt_resource *res)
+{
+ int index;
+
+ index = fdt_stringlist_search(fdt, node, prop_names, name);
+ if (index < 0)
+ return index;
+
+ return fdt_get_resource(fdt, node, property, index, res);
+}
+
+static int decode_timing_property(const void *blob, int node, const char *name,
+ struct timing_entry *result)
+{
+ int length, ret = 0;
+ const u32 *prop;
+
+ prop = fdt_getprop(blob, node, name, &length);
+ if (!prop) {
+ debug("%s: could not find property %s\n",
+ fdt_get_name(blob, node, NULL), name);
+ return length;
+ }
+
+ if (length == sizeof(u32)) {
+ result->typ = fdtdec_get_int(blob, node, name, 0);
+ result->min = result->typ;
+ result->max = result->typ;
+ } else {
+ ret = fdtdec_get_int_array(blob, node, name, &result->min, 3);
+ }
+
+ return ret;
+}
+
+int fdtdec_decode_display_timing(const void *blob, int parent, int index,
+ struct display_timing *dt)
+{
+ int i, node, timings_node;
+ u32 val = 0;
+ int ret = 0;
+
+ timings_node = fdt_subnode_offset(blob, parent, "display-timings");
+ if (timings_node < 0)
+ return timings_node;
+
+ for (i = 0, node = fdt_first_subnode(blob, timings_node);
+ node > 0 && i != index;
+ node = fdt_next_subnode(blob, node))
+ i++;
+
+ if (node < 0)
+ return node;
+
+ memset(dt, 0, sizeof(*dt));
+
+ ret |= decode_timing_property(blob, node, "hback-porch",
+ &dt->hback_porch);
+ ret |= decode_timing_property(blob, node, "hfront-porch",
+ &dt->hfront_porch);
+ ret |= decode_timing_property(blob, node, "hactive", &dt->hactive);
+ ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len);
+ ret |= decode_timing_property(blob, node, "vback-porch",
+ &dt->vback_porch);
+ ret |= decode_timing_property(blob, node, "vfront-porch",
+ &dt->vfront_porch);
+ ret |= decode_timing_property(blob, node, "vactive", &dt->vactive);
+ ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len);
+ ret |= decode_timing_property(blob, node, "clock-frequency",
+ &dt->pixelclock);
+
+ dt->flags = 0;
+ val = fdtdec_get_int(blob, node, "vsync-active", -1);
+ if (val != -1) {
+ dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+ DISPLAY_FLAGS_VSYNC_LOW;
+ }
+ val = fdtdec_get_int(blob, node, "hsync-active", -1);
+ if (val != -1) {
+ dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+ DISPLAY_FLAGS_HSYNC_LOW;
+ }
+ val = fdtdec_get_int(blob, node, "de-active", -1);
+ if (val != -1) {
+ dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+ DISPLAY_FLAGS_DE_LOW;
+ }
+ val = fdtdec_get_int(blob, node, "pixelclk-active", -1);
+ if (val != -1) {
+ dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ }
+
+ if (fdtdec_get_bool(blob, node, "interlaced"))
+ dt->flags |= DISPLAY_FLAGS_INTERLACED;
+ if (fdtdec_get_bool(blob, node, "doublescan"))
+ dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
+ if (fdtdec_get_bool(blob, node, "doubleclk"))
+ dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
+
+ return ret;
+}
+
+int fdtdec_setup_mem_size_base_fdt(const void *blob)
+{
+ int ret, mem;
+ struct fdt_resource res;
+
+ mem = fdt_path_offset(blob, "/memory");
+ if (mem < 0) {
+ debug("%s: Missing /memory node\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = fdt_get_resource(blob, mem, "reg", 0, &res);
+ if (ret != 0) {
+ debug("%s: Unable to decode first memory bank\n", __func__);
+ return -EINVAL;
+ }
+
+ gd->ram_size = (phys_size_t)(res.end - res.start + 1);
+ gd->ram_base = (unsigned long)res.start;
+ debug("%s: Initial DRAM size %llx\n", __func__,
+ (unsigned long long)gd->ram_size);
+
+ return 0;
+}
+
+int fdtdec_setup_mem_size_base(void)
+{
+ return fdtdec_setup_mem_size_base_fdt(gd->fdt_blob);
+}
+
+#if defined(CONFIG_NR_DRAM_BANKS)
+
+static int get_next_memory_node(const void *blob, int mem)
+{
+ do {
+ mem = fdt_node_offset_by_prop_value(blob, mem,
+ "device_type", "memory", 7);
+ } while (!fdtdec_get_is_enabled(blob, mem));
+
+ return mem;
+}
+
+int fdtdec_setup_memory_banksize_fdt(const void *blob)
+{
+ int bank, ret, mem, reg = 0;
+ struct fdt_resource res;
+
+ mem = get_next_memory_node(blob, -1);
+ if (mem < 0) {
+ debug("%s: Missing /memory node\n", __func__);
+ return -EINVAL;
+ }
+
+ for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+ ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
+ if (ret == -FDT_ERR_NOTFOUND) {
+ reg = 0;
+ mem = get_next_memory_node(blob, mem);
+ if (mem == -FDT_ERR_NOTFOUND)
+ break;
+
+ ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
+ if (ret == -FDT_ERR_NOTFOUND)
+ break;
+ }
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ gd->bd->bi_dram[bank].start = (phys_addr_t)res.start;
+ gd->bd->bi_dram[bank].size =
+ (phys_size_t)(res.end - res.start + 1);
+
+ debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n",
+ __func__, bank,
+ (unsigned long long)gd->bd->bi_dram[bank].start,
+ (unsigned long long)gd->bd->bi_dram[bank].size);
+ }
+
+ return 0;
+}
+
+int fdtdec_setup_memory_banksize(void)
+{
+ return fdtdec_setup_memory_banksize_fdt(gd->fdt_blob);
+
+}
+#endif
+
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\
+ CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO)
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
+{
+ size_t sz_out = CONFIG_VAL(MULTI_DTB_FIT_UNCOMPRESS_SZ);
+ bool gzip = 0, lzo = 0;
+ ulong sz_in = sz_src;
+ void *dst;
+ int rc;
+
+ if (CONFIG_IS_ENABLED(GZIP))
+ if (gzip_parse_header(src, sz_in) >= 0)
+ gzip = 1;
+ if (CONFIG_IS_ENABLED(LZO))
+ if (!gzip && lzop_is_valid_header(src))
+ lzo = 1;
+
+ if (!gzip && !lzo)
+ return -EBADMSG;
+
+
+ if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) {
+ dst = malloc(sz_out);
+ if (!dst) {
+ puts("uncompress_blob: Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ } else {
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
+ dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
+# else
+ return -ENOTSUPP;
+# endif
+ }
+
+ if (CONFIG_IS_ENABLED(GZIP) && gzip)
+ rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
+ else if (CONFIG_IS_ENABLED(LZO) && lzo)
+ rc = lzop_decompress(src, sz_in, dst, &sz_out);
+ else
+ hang();
+
+ if (rc < 0) {
+ /* not a valid compressed blob */
+ puts("uncompress_blob: Unable to uncompress\n");
+ if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC))
+ free(dst);
+ return -EBADMSG;
+ }
+ *dstp = dst;
+ return 0;
+}
+# else
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
+{
+ *dstp = (void *)src;
+ return 0;
+}
+# endif
+#endif
+
+#if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
+/*
+ * For CONFIG_OF_SEPARATE, the board may optionally implement this to
+ * provide and/or fixup the fdt.
+ */
+__weak void *board_fdt_blob_setup(void)
+{
+ void *fdt_blob = NULL;
+#ifdef CONFIG_SPL_BUILD
+ /* FDT is at end of BSS unless it is in a different memory region */
+ if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
+ fdt_blob = (ulong *)&_image_binary_end;
+ else
+ fdt_blob = (ulong *)&__bss_end;
+#else
+ /* FDT is at end of image */
+ fdt_blob = (ulong *)&_end;
+#endif
+ return fdt_blob;
+}
+#endif
+
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size)
+{
+ const char *path;
+ int offset, err;
+
+ if (!is_valid_ethaddr(mac))
+ return -EINVAL;
+
+ path = fdt_get_alias(fdt, "ethernet");
+ if (!path)
+ return 0;
+
+ debug("ethernet alias found: %s\n", path);
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0) {
+ debug("ethernet alias points to absent node %s\n", path);
+ return -ENOENT;
+ }
+
+ err = fdt_setprop_inplace(fdt, offset, "local-mac-address", mac, size);
+ if (err < 0)
+ return err;
+
+ debug("MAC address: %pM\n", mac);
+
+ return 0;
+}
+
+static int fdtdec_init_reserved_memory(void *blob)
+{
+ int na, ns, node, err;
+ fdt32_t value;
+
+ /* inherit #address-cells and #size-cells from the root node */
+ na = fdt_address_cells(blob, 0);
+ ns = fdt_size_cells(blob, 0);
+
+ node = fdt_add_subnode(blob, 0, "reserved-memory");
+ if (node < 0)
+ return node;
+
+ err = fdt_setprop(blob, node, "ranges", NULL, 0);
+ if (err < 0)
+ return err;
+
+ value = cpu_to_fdt32(ns);
+
+ err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value));
+ if (err < 0)
+ return err;
+
+ value = cpu_to_fdt32(na);
+
+ err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value));
+ if (err < 0)
+ return err;
+
+ return node;
+}
+
+int fdtdec_add_reserved_memory(void *blob, const char *basename,
+ const struct fdt_memory *carveout,
+ uint32_t *phandlep)
+{
+ fdt32_t cells[4] = {}, *ptr = cells;
+ uint32_t upper, lower, phandle;
+ int parent, node, na, ns, err;
+ fdt_size_t size;
+ char name[64];
+
+ /* create an empty /reserved-memory node if one doesn't exist */
+ parent = fdt_path_offset(blob, "/reserved-memory");
+ if (parent < 0) {
+ parent = fdtdec_init_reserved_memory(blob);
+ if (parent < 0)
+ return parent;
+ }
+
+ /* only 1 or 2 #address-cells and #size-cells are supported */
+ na = fdt_address_cells(blob, parent);
+ if (na < 1 || na > 2)
+ return -FDT_ERR_BADNCELLS;
+
+ ns = fdt_size_cells(blob, parent);
+ if (ns < 1 || ns > 2)
+ return -FDT_ERR_BADNCELLS;
+
+ /* find a matching node and return the phandle to that */
+ fdt_for_each_subnode(node, blob, parent) {
+ const char *name = fdt_get_name(blob, node, NULL);
+ phys_addr_t addr, size;
+
+ addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+ if (addr == FDT_ADDR_T_NONE) {
+ debug("failed to read address/size for %s\n", name);
+ continue;
+ }
+
+ if (addr == carveout->start && (addr + size) == carveout->end) {
+ if (phandlep)
+ *phandlep = fdt_get_phandle(blob, node);
+ return 0;
+ }
+ }
+
+ /*
+ * Unpack the start address and generate the name of the new node
+ * base on the basename and the unit-address.
+ */
+ upper = upper_32_bits(carveout->start);
+ lower = lower_32_bits(carveout->start);
+
+ if (na > 1 && upper > 0)
+ snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+ lower);
+ else {
+ if (upper > 0) {
+ debug("address %08x:%08x exceeds addressable space\n",
+ upper, lower);
+ return -FDT_ERR_BADVALUE;
+ }
+
+ snprintf(name, sizeof(name), "%s@%x", basename, lower);
+ }
+
+ node = fdt_add_subnode(blob, parent, name);
+ if (node < 0)
+ return node;
+
+ if (phandlep) {
+ err = fdt_generate_phandle(blob, &phandle);
+ if (err < 0)
+ return err;
+
+ err = fdtdec_set_phandle(blob, node, phandle);
+ if (err < 0)
+ return err;
+ }
+
+ /* store one or two address cells */
+ if (na > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ /* store one or two size cells */
+ size = carveout->end - carveout->start + 1;
+ upper = upper_32_bits(size);
+ lower = lower_32_bits(size);
+
+ if (ns > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells));
+ if (err < 0)
+ return err;
+
+ /* return the phandle for the new node for the caller to use */
+ if (phandlep)
+ *phandlep = phandle;
+
+ return 0;
+}
+
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+ unsigned int index, struct fdt_memory *carveout)
+{
+ const fdt32_t *prop;
+ uint32_t phandle;
+ int offset, len;
+ fdt_size_t size;
+
+ offset = fdt_path_offset(blob, node);
+ if (offset < 0)
+ return offset;
+
+ prop = fdt_getprop(blob, offset, name, &len);
+ if (!prop) {
+ debug("failed to get %s for %s\n", name, node);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((len % sizeof(phandle)) != 0) {
+ debug("invalid phandle property\n");
+ return -FDT_ERR_BADPHANDLE;
+ }
+
+ if (len < (sizeof(phandle) * (index + 1))) {
+ debug("invalid phandle index\n");
+ return -FDT_ERR_BADPHANDLE;
+ }
+
+ phandle = fdt32_to_cpu(prop[index]);
+
+ offset = fdt_node_offset_by_phandle(blob, phandle);
+ if (offset < 0) {
+ debug("failed to find node for phandle %u\n", phandle);
+ return offset;
+ }
+
+ carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset,
+ "reg", 0, &size,
+ true);
+ if (carveout->start == FDT_ADDR_T_NONE) {
+ debug("failed to read address/size from \"reg\" property\n");
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ carveout->end = carveout->start + size - 1;
+
+ return 0;
+}
+
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+ unsigned int index, const char *name,
+ const struct fdt_memory *carveout)
+{
+ uint32_t phandle;
+ int err, offset;
+ fdt32_t value;
+
+ /* XXX implement support for multiple phandles */
+ if (index > 0) {
+ debug("invalid index %u\n", index);
+ return -FDT_ERR_BADOFFSET;
+ }
+
+ err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
+ if (err < 0) {
+ debug("failed to add reserved memory: %d\n", err);
+ return err;
+ }
+
+ offset = fdt_path_offset(blob, node);
+ if (offset < 0) {
+ debug("failed to find offset for node %s: %d\n", node, offset);
+ return offset;
+ }
+
+ value = cpu_to_fdt32(phandle);
+
+ err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+ if (err < 0) {
+ debug("failed to set %s property for node %s: %d\n", prop_name,
+ node, err);
+ return err;
+ }
+
+ return 0;
+}
+
+int fdtdec_setup(void)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+ void *fdt_blob;
+# endif
+# ifdef CONFIG_OF_EMBED
+ /* Get a pointer to the FDT */
+# ifdef CONFIG_SPL_BUILD
+ gd->fdt_blob = __dtb_dt_spl_begin;
+# else
+ gd->fdt_blob = __dtb_dt_begin;
+# endif
+# elif defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
+ /* Allow the board to override the fdt address. */
+ gd->fdt_blob = board_fdt_blob_setup();
+# elif defined(CONFIG_OF_HOSTFILE)
+ if (sandbox_read_fdt_from_file()) {
+ puts("Failed to read control FDT\n");
+ return -1;
+ }
+# elif defined(CONFIG_OF_PRIOR_STAGE)
+ gd->fdt_blob = (void *)prior_stage_fdt_address;
+# endif
+# ifndef CONFIG_SPL_BUILD
+ /* Allow the early environment to override the fdt address */
+ gd->fdt_blob = map_sysmem
+ (env_get_ulong("fdtcontroladdr", 16,
+ (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
+# endif
+
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+ /*
+ * Try and uncompress the blob.
+ * Unfortunately there is no way to know how big the input blob really
+ * is. So let us set the maximum input size arbitrarily high. 16MB
+ * ought to be more than enough for packed DTBs.
+ */
+ if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
+ gd->fdt_blob = fdt_blob;
+
+ /*
+ * Check if blob is a FIT images containings DTBs.
+ * If so, pick the most relevant
+ */
+ fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
+ if (fdt_blob) {
+ gd->multi_dtb_fit = gd->fdt_blob;
+ gd->fdt_blob = fdt_blob;
+ }
+
+# endif
+#endif
+
+ return fdtdec_prepare_fdt();
+}
+
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+int fdtdec_resetup(int *rescan)
+{
+ void *fdt_blob;
+
+ /*
+ * If the current DTB is part of a compressed FIT image,
+ * try to locate the best match from the uncompressed
+ * FIT image stillpresent there. Save the time and space
+ * required to uncompress it again.
+ */
+ if (gd->multi_dtb_fit) {
+ fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit);
+
+ if (fdt_blob == gd->fdt_blob) {
+ /*
+ * The best match did not change. no need to tear down
+ * the DM and rescan the fdt.
+ */
+ *rescan = 0;
+ return 0;
+ }
+
+ *rescan = 1;
+ gd->fdt_blob = fdt_blob;
+ return fdtdec_prepare_fdt();
+ }
+
+ /*
+ * If multi_dtb_fit is NULL, it means that blob appended to u-boot is
+ * not a FIT image containings DTB, but a single DTB. There is no need
+ * to teard down DM and rescan the DT in this case.
+ */
+ *rescan = 0;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_NR_DRAM_BANKS
+int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
+ phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)
+{
+ int addr_cells, size_cells;
+ const u32 *cell, *end;
+ u64 total_size, size, addr;
+ int node, child;
+ bool auto_size;
+ int bank;
+ int len;
+
+ debug("%s: board_id=%d\n", __func__, board_id);
+ if (!area)
+ area = "/memory";
+ node = fdt_path_offset(blob, area);
+ if (node < 0) {
+ debug("No %s node found\n", area);
+ return -ENOENT;
+ }
+
+ cell = fdt_getprop(blob, node, "reg", &len);
+ if (!cell) {
+ debug("No reg property found\n");
+ return -ENOENT;
+ }
+
+ addr_cells = fdt_address_cells(blob, node);
+ size_cells = fdt_size_cells(blob, node);
+
+ /* Check the board id and mask */
+ for (child = fdt_first_subnode(blob, node);
+ child >= 0;
+ child = fdt_next_subnode(blob, child)) {
+ int match_mask, match_value;
+
+ match_mask = fdtdec_get_int(blob, child, "match-mask", -1);
+ match_value = fdtdec_get_int(blob, child, "match-value", -1);
+
+ if (match_value >= 0 &&
+ ((board_id & match_mask) == match_value)) {
+ /* Found matching mask */
+ debug("Found matching mask %d\n", match_mask);
+ node = child;
+ cell = fdt_getprop(blob, node, "reg", &len);
+ if (!cell) {
+ debug("No memory-banks property found\n");
+ return -EINVAL;
+ }
+ break;
+ }
+ }
+ /* Note: if no matching subnode was found we use the parent node */
+
+ if (bd) {
+ memset(bd->bi_dram, '\0', sizeof(bd->bi_dram[0]) *
+ CONFIG_NR_DRAM_BANKS);
+ }
+
+ auto_size = fdtdec_get_bool(blob, node, "auto-size");
+
+ total_size = 0;
+ end = cell + len / 4 - addr_cells - size_cells;
+ debug("cell at %p, end %p\n", cell, end);
+ for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+ if (cell > end)
+ break;
+ addr = 0;
+ if (addr_cells == 2)
+ addr += (u64)fdt32_to_cpu(*cell++) << 32UL;
+ addr += fdt32_to_cpu(*cell++);
+ if (bd)
+ bd->bi_dram[bank].start = addr;
+ if (basep && !bank)
+ *basep = (phys_addr_t)addr;
+
+ size = 0;
+ if (size_cells == 2)
+ size += (u64)fdt32_to_cpu(*cell++) << 32UL;
+ size += fdt32_to_cpu(*cell++);
+
+ if (auto_size) {
+ u64 new_size;
+
+ debug("Auto-sizing %llx, size %llx: ", addr, size);
+ new_size = get_ram_size((long *)(uintptr_t)addr, size);
+ if (new_size == size) {
+ debug("OK\n");
+ } else {
+ debug("sized to %llx\n", new_size);
+ size = new_size;
+ }
+ }
+
+ if (bd)
+ bd->bi_dram[bank].size = size;
+ total_size += size;
+ }
+
+ debug("Memory size %llu\n", total_size);
+ if (sizep)
+ *sizep = (phys_size_t)total_size;
+
+ return 0;
+}
+#endif /* CONFIG_NR_DRAM_BANKS */
+
+#endif /* !USE_HOSTCC */
diff --git a/lib/fdtdec_common.c b/lib/fdtdec_common.c
new file mode 100644
index 00000000..088e9e90
--- /dev/null
+++ b/lib/fdtdec_common.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2014
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * Based on lib/fdtdec.c:
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <linux/libfdt.h>
+#include <fdtdec.h>
+#else
+#include "libfdt.h"
+#include "fdt_support.h"
+
+#define debug(...)
+#endif
+
+int fdtdec_get_int(const void *blob, int node, const char *prop_name,
+ int default_val)
+{
+ const int *cell;
+ int len;
+
+ debug("%s: %s: ", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ if (cell && len >= sizeof(int)) {
+ int val = fdt32_to_cpu(cell[0]);
+
+ debug("%#x (%d)\n", val, val);
+ return val;
+ }
+ debug("(not found)\n");
+ return default_val;
+}
+
+unsigned int fdtdec_get_uint(const void *blob, int node, const char *prop_name,
+ unsigned int default_val)
+{
+ const int *cell;
+ int len;
+
+ debug("%s: %s: ", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ if (cell && len >= sizeof(unsigned int)) {
+ unsigned int val = fdt32_to_cpu(cell[0]);
+
+ debug("%#x (%d)\n", val, val);
+ return val;
+ }
+ debug("(not found)\n");
+ return default_val;
+}
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c
new file mode 100644
index 00000000..e8bfd1fb
--- /dev/null
+++ b/lib/fdtdec_test.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Some very basic tests for fdtdec, accessed through test_fdtdec command.
+ * They are easiest to use with sandbox.
+ *
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <linux/libfdt.h>
+#include <malloc.h>
+#include <os.h>
+
+/* The size of our test fdt blob */
+#define FDT_SIZE (16 * 1024)
+
+#define CHECK(op) ({ \
+ int err = op; \
+ if (err < 0) { \
+ printf("%s: %s: %s\n", __func__, #op, \
+ fdt_strerror(err)); \
+ return err; \
+ } \
+ \
+ err; \
+ })
+
+#define CHECKVAL(op, expected) ({ \
+ int err = op; \
+ if (err != expected) { \
+ printf("%s: %s: expected %d, but returned %d\n",\
+ __func__, #op, expected, err); \
+ return err; \
+ } \
+ \
+ err; \
+ })
+
+#define CHECKOK(op) CHECKVAL(op, 0)
+
+/* maximum number of nodes / aliases to generate */
+#define MAX_NODES 20
+
+/*
+ * Make a test fdt
+ *
+ * @param fdt Device tree pointer
+ * @param size Size of device tree blob
+ * @param aliases Specifies alias assignments. Format is a list of items
+ * separated by space. Items are #a where
+ * # is the alias number
+ * a is the node to point to
+ * @param nodes Specifies nodes to generate (a=0, b=1), upper case
+ * means to create a disabled node
+ */
+static int make_fdt(void *fdt, int size, const char *aliases,
+ const char *nodes)
+{
+ char name[20], value[20];
+ const char *s;
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ int fd;
+#endif
+
+ CHECK(fdt_create(fdt, size));
+ CHECK(fdt_finish_reservemap(fdt));
+ CHECK(fdt_begin_node(fdt, ""));
+
+ CHECK(fdt_begin_node(fdt, "aliases"));
+ for (s = aliases; *s;) {
+ sprintf(name, "i2c%c", *s);
+ sprintf(value, "/i2c%d@0", s[1] - 'a');
+ CHECK(fdt_property_string(fdt, name, value));
+ s += 2 + (s[2] != '\0');
+ }
+ CHECK(fdt_end_node(fdt));
+
+ for (s = nodes; *s; s++) {
+ sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A');
+ CHECK(fdt_begin_node(fdt, value));
+ CHECK(fdt_property_string(fdt, "compatible",
+ fdtdec_get_compatible(COMPAT_UNKNOWN)));
+ if (*s <= 'Z')
+ CHECK(fdt_property_string(fdt, "status", "disabled"));
+ CHECK(fdt_end_node(fdt));
+ }
+
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_finish(fdt));
+ CHECK(fdt_pack(fdt));
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY);
+ if (fd == -1) {
+ printf("Could not open .dtb file to write\n");
+ return -1;
+ }
+ os_write(fd, fdt, size);
+ os_close(fd);
+#endif
+ return 0;
+}
+
+static int run_test(const char *aliases, const char *nodes, const char *expect)
+{
+ int list[MAX_NODES];
+ const char *s;
+ void *blob;
+ int i;
+
+ blob = malloc(FDT_SIZE);
+ if (!blob) {
+ printf("%s: out of memory\n", __func__);
+ return 1;
+ }
+
+ printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect);
+ CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0);
+ CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c",
+ COMPAT_UNKNOWN,
+ list, ARRAY_SIZE(list)), (int)strlen(expect));
+
+ /* Check we got the right ones */
+ for (i = 0, s = expect; *s; s++, i++) {
+ int want = *s;
+ const char *name;
+ int got = ' ';
+
+ name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL;
+ if (name)
+ got = name[3] + 'a' - '0';
+
+ if (got != want) {
+ printf("Position %d: Expected '%c', got '%c' ('%s')\n",
+ i, want, got, name);
+ return 1;
+ }
+ }
+
+ printf("pass\n");
+ free(blob);
+ return 0;
+}
+
+static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns)
+{
+ const char *basename = "/display";
+ struct fdt_memory carveout = {
+#ifdef CONFIG_PHYS_64BIT
+ .start = 0x180000000,
+ .end = 0x18fffffff,
+#else
+ .start = 0x80000000,
+ .end = 0x8fffffff,
+#endif
+ };
+ fdt32_t cells[4], *ptr = cells;
+ uint32_t upper, lower;
+ fdt_size_t size;
+ char name[32];
+ int offset;
+
+ /* store one or two address cells */
+ upper = upper_32_bits(carveout.start);
+ lower = lower_32_bits(carveout.start);
+
+ if (na > 1 && upper > 0)
+ snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+ lower);
+ else
+ snprintf(name, sizeof(name), "%s@%x", basename, lower);
+
+ if (na > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ /* store one or two size cells */
+ size = carveout.end - carveout.start + 1;
+ upper = upper_32_bits(size);
+ lower = lower_32_bits(size);
+
+ if (ns > 1)
+ *ptr++ = cpu_to_fdt32(upper);
+
+ *ptr++ = cpu_to_fdt32(lower);
+
+ offset = CHECK(fdt_add_subnode(fdt, 0, name + 1));
+ CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells)));
+
+ return fdtdec_set_carveout(fdt, name, "memory-region", 0,
+ "framebuffer", &carveout);
+}
+
+static int check_fdt_carveout(void *fdt, uint32_t address_cells,
+ uint32_t size_cells)
+{
+#ifdef CONFIG_PHYS_64BIT
+ const char *name = "/display@1,80000000";
+ const struct fdt_memory expected = {
+ .start = 0x180000000,
+ .end = 0x18fffffff,
+ };
+#else
+ const char *name = "/display@80000000";
+ const struct fdt_memory expected = {
+ .start = 0x80000000,
+ .end = 0x8fffffff,
+ };
+#endif
+ struct fdt_memory carveout;
+
+ printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start,
+ &expected.end, address_cells, size_cells);
+
+ CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout));
+
+ if ((carveout.start != expected.start) ||
+ (carveout.end != expected.end)) {
+ printf("carveout: %pap-%pap, expected %pap-%pap\n",
+ &carveout.start, &carveout.end,
+ &expected.start, &expected.end);
+ return 1;
+ }
+
+ printf("pass\n");
+ return 0;
+}
+
+static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells,
+ uint32_t size_cells)
+{
+ fdt32_t na = cpu_to_fdt32(address_cells);
+ fdt32_t ns = cpu_to_fdt32(size_cells);
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ char filename[512];
+ int fd;
+#endif
+ int err;
+
+ CHECK(fdt_create(fdt, size));
+ CHECK(fdt_finish_reservemap(fdt));
+ CHECK(fdt_begin_node(fdt, ""));
+ CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na)));
+ CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns)));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_finish(fdt));
+ CHECK(fdt_pack(fdt));
+
+ CHECK(fdt_open_into(fdt, fdt, FDT_SIZE));
+
+ err = make_fdt_carveout_device(fdt, address_cells, size_cells);
+
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+ snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb",
+ address_cells, size_cells);
+
+ fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY);
+ if (fd < 0) {
+ printf("could not open .dtb file to write\n");
+ goto out;
+ }
+
+ os_write(fd, fdt, size);
+ os_close(fd);
+
+out:
+#endif
+ return err;
+}
+
+static int check_carveout(void)
+{
+ void *fdt;
+
+ fdt = malloc(FDT_SIZE);
+ if (!fdt) {
+ printf("%s: out of memory\n", __func__);
+ return 1;
+ }
+
+#ifndef CONFIG_PHYS_64BIT
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0);
+ CHECKOK(check_fdt_carveout(fdt, 1, 1));
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0);
+ CHECKOK(check_fdt_carveout(fdt, 1, 2));
+#else
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE);
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE);
+#endif
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0);
+ CHECKOK(check_fdt_carveout(fdt, 2, 1));
+ CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0);
+ CHECKOK(check_fdt_carveout(fdt, 2, 2));
+
+ free(fdt);
+ return 0;
+}
+
+static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ /* basic tests */
+ CHECKOK(run_test("", "", ""));
+ CHECKOK(run_test("1e 3d", "", ""));
+
+ /*
+ * 'a' represents 0, 'b' represents 1, etc.
+ * The first character is the alias number, the second is the node
+ * number. So the params mean:
+ * 0a 1b : point alias 0 to node 0 (a), alias 1 to node 1(b)
+ * ab : to create nodes 0 and 1 (a and b)
+ * ab : we expect the function to return two nodes, in
+ * the order 0, 1
+ */
+ CHECKOK(run_test("0a 1b", "ab", "ab"));
+
+ CHECKOK(run_test("0a 1c", "ab", "ab"));
+ CHECKOK(run_test("1c", "ab", "ab"));
+ CHECKOK(run_test("1b", "ab", "ab"));
+ CHECKOK(run_test("0b", "ab", "ba"));
+ CHECKOK(run_test("0b 2d", "dbc", "bcd"));
+ CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba"));
+
+ /* things with holes */
+ CHECKOK(run_test("1b 3d", "dbc", "cb d"));
+ CHECKOK(run_test("1e 3d", "dbc", "bc d"));
+
+ /* no aliases */
+ CHECKOK(run_test("", "dbac", "dbac"));
+
+ /* disabled nodes */
+ CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a"));
+ CHECKOK(run_test("0b 2d", "DBc", "c"));
+ CHECKOK(run_test("0b 4d 2c", "DBc", " c"));
+
+ /* conflicting aliases - first one gets it */
+ CHECKOK(run_test("2a 1a 0a", "a", " a"));
+ CHECKOK(run_test("0a 1a 2a", "a", "a"));
+
+ CHECKOK(check_carveout());
+
+ printf("Test passed\n");
+ return 0;
+}
+
+U_BOOT_CMD(
+ test_fdtdec, 3, 1, do_test_fdtdec,
+ "test_fdtdec",
+ "Run tests for fdtdec library");
diff --git a/lib/gunzip.c b/lib/gunzip.c
new file mode 100644
index 00000000..9e6ccd69
--- /dev/null
+++ b/lib/gunzip.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <div64.h>
+#include <gzip.h>
+#include <image.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <u-boot/crc.h>
+#include <watchdog.h>
+#include <u-boot/zlib.h>
+
+#define HEADER0 '\x1f'
+#define HEADER1 '\x8b'
+#define ZALLOC_ALIGNMENT 16
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+#define DEFLATED 8
+
+void *gzalloc(void *x, unsigned items, unsigned size)
+{
+ void *p;
+
+ size *= items;
+ size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+ p = malloc (size);
+
+ return (p);
+}
+
+void gzfree(void *x, void *addr, unsigned nb)
+{
+ free (addr);
+}
+
+int gzip_parse_header(const unsigned char *src, unsigned long len)
+{
+ int i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ puts ("Error: Bad gzipped data\n");
+ return (-1);
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= len) {
+ puts ("Error: gunzip out of data in header\n");
+ return (-1);
+ }
+ return i;
+}
+
+int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+{
+ int offset = gzip_parse_header(src, *lenp);
+
+ if (offset < 0)
+ return offset;
+
+ return zunzip(dst, dstlen, src, lenp, 1, offset);
+}
+
+#ifdef CONFIG_CMD_UNZIP
+__weak
+void gzwrite_progress_init(u64 expectedsize)
+{
+ putc('\n');
+}
+
+__weak
+void gzwrite_progress(int iteration,
+ u64 bytes_written,
+ u64 total_bytes)
+{
+ if (0 == (iteration & 3))
+ printf("%llu/%llu\r", bytes_written, total_bytes);
+}
+
+__weak
+void gzwrite_progress_finish(int returnval,
+ u64 bytes_written,
+ u64 total_bytes,
+ u32 expected_crc,
+ u32 calculated_crc)
+{
+ if (0 == returnval) {
+ printf("\n\t%llu bytes, crc 0x%08x\n",
+ total_bytes, calculated_crc);
+ } else {
+ printf("\n\tuncompressed %llu of %llu\n"
+ "\tcrcs == 0x%08x/0x%08x\n",
+ bytes_written, total_bytes,
+ expected_crc, calculated_crc);
+ }
+}
+
+int gzwrite(unsigned char *src, int len,
+ struct blk_desc *dev,
+ unsigned long szwritebuf,
+ u64 startoffs,
+ u64 szexpected)
+{
+ int i, flags;
+ z_stream s;
+ int r = 0;
+ unsigned char *writebuf;
+ unsigned crc = 0;
+ u64 totalfilled = 0;
+ lbaint_t blksperbuf, outblock;
+ u32 expected_crc;
+ u32 payload_size;
+ int iteration = 0;
+
+ if (!szwritebuf ||
+ (szwritebuf % dev->blksz) ||
+ (szwritebuf < dev->blksz)) {
+ printf("%s: size %lu not a multiple of %lu\n",
+ __func__, szwritebuf, dev->blksz);
+ return -1;
+ }
+
+ if (startoffs & (dev->blksz-1)) {
+ printf("%s: start offset %llu not a multiple of %lu\n",
+ __func__, startoffs, dev->blksz);
+ return -1;
+ }
+
+ blksperbuf = szwritebuf / dev->blksz;
+ outblock = lldiv(startoffs, dev->blksz);
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ puts("Error: Bad gzipped data\n");
+ return -1;
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+
+ if (i >= len-8) {
+ puts("Error: gunzip out of data in header");
+ return -1;
+ }
+
+ payload_size = len - i - 8;
+
+ memcpy(&expected_crc, src + len - 8, sizeof(expected_crc));
+ expected_crc = le32_to_cpu(expected_crc);
+ u32 szuncompressed;
+ memcpy(&szuncompressed, src + len - 4, sizeof(szuncompressed));
+ if (szexpected == 0) {
+ szexpected = le32_to_cpu(szuncompressed);
+ } else if (szuncompressed != (u32)szexpected) {
+ printf("size of %llx doesn't match trailer low bits %x\n",
+ szexpected, szuncompressed);
+ return -1;
+ }
+ if (lldiv(szexpected, dev->blksz) > (dev->lba - outblock)) {
+ printf("%s: uncompressed size %llu exceeds device size\n",
+ __func__, szexpected);
+ return -1;
+ }
+
+ gzwrite_progress_init(szexpected);
+
+ s.zalloc = gzalloc;
+ s.zfree = gzfree;
+
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("Error: inflateInit2() returned %d\n", r);
+ return -1;
+ }
+
+ s.next_in = src + i;
+ s.avail_in = payload_size+8;
+ writebuf = (unsigned char *)malloc_cache_aligned(szwritebuf);
+
+ /* decompress until deflate stream ends or end of file */
+ do {
+ if (s.avail_in == 0) {
+ printf("%s: weird termination with result %d\n",
+ __func__, r);
+ break;
+ }
+
+ /* run inflate() on input until output buffer not full */
+ do {
+ unsigned long blocks_written;
+ int numfilled;
+ lbaint_t writeblocks;
+
+ s.avail_out = szwritebuf;
+ s.next_out = writebuf;
+ r = inflate(&s, Z_SYNC_FLUSH);
+ if ((r != Z_OK) &&
+ (r != Z_STREAM_END)) {
+ printf("Error: inflate() returned %d\n", r);
+ goto out;
+ }
+ numfilled = szwritebuf - s.avail_out;
+ crc = crc32(crc, writebuf, numfilled);
+ totalfilled += numfilled;
+ if (numfilled < szwritebuf) {
+ writeblocks = (numfilled+dev->blksz-1)
+ / dev->blksz;
+ memset(writebuf+numfilled, 0,
+ dev->blksz-(numfilled%dev->blksz));
+ } else {
+ writeblocks = blksperbuf;
+ }
+
+ gzwrite_progress(iteration++,
+ totalfilled,
+ szexpected);
+ blocks_written = blk_dwrite(dev, outblock,
+ writeblocks, writebuf);
+ outblock += blocks_written;
+ if (ctrlc()) {
+ puts("abort\n");
+ goto out;
+ }
+ WATCHDOG_RESET();
+ } while (s.avail_out == 0);
+ /* done when inflate() says it's done */
+ } while (r != Z_STREAM_END);
+
+ if ((szexpected != totalfilled) ||
+ (crc != expected_crc))
+ r = -1;
+ else
+ r = 0;
+
+out:
+ gzwrite_progress_finish(r, totalfilled, szexpected,
+ expected_crc, crc);
+ free(writebuf);
+ inflateEnd(&s);
+
+ return r;
+}
+#endif
+
+/*
+ * Uncompress blocks compressed with zlib without headers
+ */
+int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
+ int stoponerr, int offset)
+{
+ z_stream s;
+ int err = 0;
+ int r;
+
+ s.zalloc = gzalloc;
+ s.zfree = gzfree;
+
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("Error: inflateInit2() returned %d\n", r);
+ return -1;
+ }
+ s.next_in = src + offset;
+ s.avail_in = *lenp - offset;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ do {
+ r = inflate(&s, Z_FINISH);
+ if (stoponerr == 1 && r != Z_STREAM_END &&
+ (s.avail_in == 0 || s.avail_out == 0 || r != Z_BUF_ERROR)) {
+ printf("Error: inflate() returned %d\n", r);
+ err = -1;
+ break;
+ }
+ } while (r == Z_BUF_ERROR);
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+
+ return err;
+}
diff --git a/lib/gzip.c b/lib/gzip.c
new file mode 100644
index 00000000..c6c0ec88
--- /dev/null
+++ b/lib/gzip.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012
+ * Lei Wen <leiwen@marvell.com>, Marvell Inc.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <gzip.h>
+#include <image.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <u-boot/zlib.h>
+#include "zlib/zutil.h"
+
+#ifndef CONFIG_GZIP_COMPRESS_DEF_SZ
+#define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200
+#endif
+#define ZALLOC_ALIGNMENT 16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p;
+
+ size *= items;
+ size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+ p = malloc_cache_aligned(size);
+
+ return (p);
+}
+
+static void zfree(void *x, void *addr, unsigned nb)
+{
+ free (addr);
+}
+
+int gzip(void *dst, unsigned long *lenp,
+ unsigned char *src, unsigned long srclen)
+{
+ return zzip(dst, lenp, src, srclen, 1, NULL);
+}
+
+/*
+ * Compress blocks with zlib
+ */
+int zzip(void *dst, unsigned long *lenp, unsigned char *src,
+ unsigned long srclen, int stoponerr,
+ int (*func)(unsigned long, unsigned long))
+{
+ z_stream s;
+ int r, flush, orig, window;
+ unsigned long comp_len, left_len;
+
+ if (!srclen)
+ return 0;
+
+#ifndef CONFIG_GZIP
+ window = MAX_WBITS;
+#else
+ window = 2 * MAX_WBITS;
+#endif
+ orig = *lenp;
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ s.opaque = Z_NULL;
+
+ r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window,
+ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+ ZLIB_VERSION, sizeof(z_stream));
+ if (r != Z_OK) {
+ printf ("Error: deflateInit2_() returned %d\n", r);
+ return -1;
+ }
+
+ while (srclen > 0) {
+ comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
+ CONFIG_GZIP_COMPRESS_DEF_SZ : srclen;
+
+ s.next_in = src;
+ s.avail_in = comp_len;
+ flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)?
+ Z_NO_FLUSH : Z_FINISH;
+
+ do {
+ left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
+ CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp;
+ s.next_out = dst;
+ s.avail_out = left_len;
+ r = deflate(&s, flush);
+ if (r == Z_STREAM_ERROR && stoponerr == 1) {
+ printf("Error: deflate() returned %d\n", r);
+ r = -1;
+ goto bail;
+ }
+ if (!func) {
+ dst += (left_len - s.avail_out);
+ *lenp -= (left_len - s.avail_out);
+ } else if (left_len - s.avail_out > 0) {
+ r = func((unsigned long)dst,
+ left_len - s.avail_out);
+ if (r < 0)
+ goto bail;
+ }
+ } while (s.avail_out == 0 && (*lenp > 0));
+ if (s.avail_in) {
+ printf("Deflate failed to consume %u bytes", s.avail_in);
+ r = -1;
+ goto bail;
+ }
+ if (*lenp == 0) {
+ printf("Deflate need more space to compress "
+ "left %lu bytes\n", srclen);
+ r = -1;
+ goto bail;
+ }
+ srclen -= comp_len;
+ src += comp_len;
+ }
+
+ r = 0;
+bail:
+ deflateEnd(&s);
+ *lenp = orig - *lenp;
+ return r;
+}
diff --git a/lib/hang.c b/lib/hang.c
new file mode 100644
index 00000000..4d026a3e
--- /dev/null
+++ b/lib/hang.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * Andreas Bießmann <andreas@biessmann.org>
+ *
+ * This file consolidates all the different hang() functions implemented in
+ * u-boot.
+ */
+
+#include <common.h>
+#include <bootstage.h>
+#include <os.h>
+
+/**
+ * hang - stop processing by staying in an endless loop
+ *
+ * The purpose of this function is to stop further execution of code cause
+ * something went completely wrong. To catch this and give some feedback to
+ * the user one needs to catch the bootstage_error (see show_boot_progress())
+ * in the board code.
+ */
+void hang(void)
+{
+#if !defined(CONFIG_SPL_BUILD) || \
+ (CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) && \
+ CONFIG_IS_ENABLED(SERIAL_SUPPORT))
+ puts("### ERROR ### Please RESET the board ###\n");
+#endif
+ bootstage_error(BOOTSTAGE_ID_NEED_RESET);
+ if (IS_ENABLED(CONFIG_SANDBOX))
+ os_exit(1);
+ for (;;)
+ ;
+}
diff --git a/lib/hashtable.c b/lib/hashtable.c
new file mode 100644
index 00000000..907e8a64
--- /dev/null
+++ b/lib/hashtable.c
@@ -0,0 +1,996 @@
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * This implementation is based on code from uClibc-0.9.30.3 but was
+ * modified and extended for use within U-Boot.
+ *
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
+ *
+ * Original license header:
+ *
+ * Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <sort.h>
+
+#ifdef USE_HOSTCC /* HOST build */
+# include <string.h>
+# include <assert.h>
+# include <ctype.h>
+
+# ifndef debug
+# ifdef DEBUG
+# define debug(fmt,args...) printf(fmt ,##args)
+# else
+# define debug(fmt,args...)
+# endif
+# endif
+#else /* U-Boot build */
+# include <common.h>
+# include <linux/string.h>
+# include <linux/ctype.h>
+#endif
+
+#ifndef CONFIG_ENV_MIN_ENTRIES /* minimum number of entries */
+#define CONFIG_ENV_MIN_ENTRIES 64
+#endif
+#ifndef CONFIG_ENV_MAX_ENTRIES /* maximum number of entries */
+#define CONFIG_ENV_MAX_ENTRIES 512
+#endif
+
+#define USED_FREE 0
+#define USED_DELETED -1
+
+#include <env_callback.h>
+#include <env_flags.h>
+#include <search.h>
+#include <slre.h>
+
+/*
+ * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
+ * [Knuth] The Art of Computer Programming, part 3 (6.4)
+ */
+
+/*
+ * The reentrant version has no static variables to maintain the state.
+ * Instead the interface of all functions is extended to take an argument
+ * which describes the current status.
+ */
+
+struct env_entry_node {
+ int used;
+ struct env_entry entry;
+};
+
+
+static void _hdelete(const char *key, struct hsearch_data *htab,
+ struct env_entry *ep, int idx);
+
+/*
+ * hcreate()
+ */
+
+/*
+ * For the used double hash method the table size has to be a prime. To
+ * correct the user given table size we need a prime test. This trivial
+ * algorithm is adequate because
+ * a) the code is (most probably) called a few times per program run and
+ * b) the number is small because the table must fit in the core
+ * */
+static int isprime(unsigned int number)
+{
+ /* no even number will be passed */
+ unsigned int div = 3;
+
+ while (div * div < number && number % div != 0)
+ div += 2;
+
+ return number % div != 0;
+}
+
+/*
+ * Before using the hash table we must allocate memory for it.
+ * Test for an existing table are done. We allocate one element
+ * more as the found prime number says. This is done for more effective
+ * indexing as explained in the comment for the hsearch function.
+ * The contents of the table is zeroed, especially the field used
+ * becomes zero.
+ */
+
+int hcreate_r(size_t nel, struct hsearch_data *htab)
+{
+ /* Test for correct arguments. */
+ if (htab == NULL) {
+ __set_errno(EINVAL);
+ return 0;
+ }
+
+ /* There is still another table active. Return with error. */
+ if (htab->table != NULL)
+ return 0;
+
+ /* Change nel to the first prime number not smaller as nel. */
+ nel |= 1; /* make odd */
+ while (!isprime(nel))
+ nel += 2;
+
+ htab->size = nel;
+ htab->filled = 0;
+
+ /* allocate memory and zero out */
+ htab->table = (struct env_entry_node *)calloc(htab->size + 1,
+ sizeof(struct env_entry_node));
+ if (htab->table == NULL)
+ return 0;
+
+ /* everything went alright */
+ return 1;
+}
+
+
+/*
+ * hdestroy()
+ */
+
+/*
+ * After using the hash table it has to be destroyed. The used memory can
+ * be freed and the local static variable can be marked as not used.
+ */
+
+void hdestroy_r(struct hsearch_data *htab)
+{
+ int i;
+
+ /* Test for correct arguments. */
+ if (htab == NULL) {
+ __set_errno(EINVAL);
+ return;
+ }
+
+ /* free used memory */
+ for (i = 1; i <= htab->size; ++i) {
+ if (htab->table[i].used > 0) {
+ struct env_entry *ep = &htab->table[i].entry;
+
+ free((void *)ep->key);
+ free(ep->data);
+ }
+ }
+ free(htab->table);
+
+ /* the sign for an existing table is an value != NULL in htable */
+ htab->table = NULL;
+}
+
+/*
+ * hsearch()
+ */
+
+/*
+ * This is the search function. It uses double hashing with open addressing.
+ * The argument item.key has to be a pointer to an zero terminated, most
+ * probably strings of chars. The function for generating a number of the
+ * strings is simple but fast. It can be replaced by a more complex function
+ * like ajw (see [Aho,Sethi,Ullman]) if the needs are shown.
+ *
+ * We use an trick to speed up the lookup. The table is created by hcreate
+ * with one more element available. This enables us to use the index zero
+ * special. This index will never be used because we store the first hash
+ * index in the field used where zero means not used. Every other value
+ * means used. The used field can be used as a first fast comparison for
+ * equality of the stored and the parameter value. This helps to prevent
+ * unnecessary expensive calls of strcmp.
+ *
+ * This implementation differs from the standard library version of
+ * this function in a number of ways:
+ *
+ * - While the standard version does not make any assumptions about
+ * the type of the stored data objects at all, this implementation
+ * works with NUL terminated strings only.
+ * - Instead of storing just pointers to the original objects, we
+ * create local copies so the caller does not need to care about the
+ * data any more.
+ * - The standard implementation does not provide a way to update an
+ * existing entry. This version will create a new entry or update an
+ * existing one when both "action == ENV_ENTER" and "item.data != NULL".
+ * - Instead of returning 1 on success, we return the index into the
+ * internal hash table, which is also guaranteed to be positive.
+ * This allows us direct access to the found hash table slot for
+ * example for functions like hdelete().
+ */
+
+int hmatch_r(const char *match, int last_idx, struct env_entry **retval,
+ struct hsearch_data *htab)
+{
+ unsigned int idx;
+ size_t key_len = strlen(match);
+
+ for (idx = last_idx + 1; idx < htab->size; ++idx) {
+ if (htab->table[idx].used <= 0)
+ continue;
+ if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
+ *retval = &htab->table[idx].entry;
+ return idx;
+ }
+ }
+
+ __set_errno(ESRCH);
+ *retval = NULL;
+ return 0;
+}
+
+/*
+ * Compare an existing entry with the desired key, and overwrite if the action
+ * is ENV_ENTER. This is simply a helper function for hsearch_r().
+ */
+static inline int _compare_and_overwrite_entry(struct env_entry item,
+ enum env_action action, struct env_entry **retval,
+ struct hsearch_data *htab, int flag, unsigned int hval,
+ unsigned int idx)
+{
+ if (htab->table[idx].used == hval
+ && strcmp(item.key, htab->table[idx].entry.key) == 0) {
+ /* Overwrite existing value? */
+ if (action == ENV_ENTER && item.data) {
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data,
+ env_op_overwrite, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ __set_errno(EPERM);
+ *retval = NULL;
+ return 0;
+ }
+
+ /* If there is a callback, call it */
+ if (htab->table[idx].entry.callback &&
+ htab->table[idx].entry.callback(item.key,
+ item.data, env_op_overwrite, flag)) {
+ debug("callback() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ __set_errno(EINVAL);
+ *retval = NULL;
+ return 0;
+ }
+
+ free(htab->table[idx].entry.data);
+ htab->table[idx].entry.data = strdup(item.data);
+ if (!htab->table[idx].entry.data) {
+ __set_errno(ENOMEM);
+ *retval = NULL;
+ return 0;
+ }
+ }
+ /* return found entry */
+ *retval = &htab->table[idx].entry;
+ return idx;
+ }
+ /* keep searching */
+ return -1;
+}
+
+int hsearch_r(struct env_entry item, enum env_action action,
+ struct env_entry **retval, struct hsearch_data *htab, int flag)
+{
+ unsigned int hval;
+ unsigned int count;
+ unsigned int len = strlen(item.key);
+ unsigned int idx;
+ unsigned int first_deleted = 0;
+ int ret;
+
+ /* Compute an value for the given string. Perhaps use a better method. */
+ hval = len;
+ count = len;
+ while (count-- > 0) {
+ hval <<= 4;
+ hval += item.key[count];
+ }
+
+ /*
+ * First hash function:
+ * simply take the modul but prevent zero.
+ */
+ hval %= htab->size;
+ if (hval == 0)
+ ++hval;
+
+ /* The first index tried. */
+ idx = hval;
+
+ if (htab->table[idx].used) {
+ /*
+ * Further action might be required according to the
+ * action value.
+ */
+ unsigned hval2;
+
+ if (htab->table[idx].used == USED_DELETED
+ && !first_deleted)
+ first_deleted = idx;
+
+ ret = _compare_and_overwrite_entry(item, action, retval, htab,
+ flag, hval, idx);
+ if (ret != -1)
+ return ret;
+
+ /*
+ * Second hash function:
+ * as suggested in [Knuth]
+ */
+ hval2 = 1 + hval % (htab->size - 2);
+
+ do {
+ /*
+ * Because SIZE is prime this guarantees to
+ * step through all available indices.
+ */
+ if (idx <= hval2)
+ idx = htab->size + idx - hval2;
+ else
+ idx -= hval2;
+
+ /*
+ * If we visited all entries leave the loop
+ * unsuccessfully.
+ */
+ if (idx == hval)
+ break;
+
+ if (htab->table[idx].used == USED_DELETED
+ && !first_deleted)
+ first_deleted = idx;
+
+ /* If entry is found use it. */
+ ret = _compare_and_overwrite_entry(item, action, retval,
+ htab, flag, hval, idx);
+ if (ret != -1)
+ return ret;
+ }
+ while (htab->table[idx].used != USED_FREE);
+ }
+
+ /* An empty bucket has been found. */
+ if (action == ENV_ENTER) {
+ /*
+ * If table is full and another entry should be
+ * entered return with error.
+ */
+ if (htab->filled == htab->size) {
+ __set_errno(ENOMEM);
+ *retval = NULL;
+ return 0;
+ }
+
+ /*
+ * Create new entry;
+ * create copies of item.key and item.data
+ */
+ if (first_deleted)
+ idx = first_deleted;
+
+ htab->table[idx].used = hval;
+ htab->table[idx].entry.key = strdup(item.key);
+ htab->table[idx].entry.data = strdup(item.data);
+ if (!htab->table[idx].entry.key ||
+ !htab->table[idx].entry.data) {
+ __set_errno(ENOMEM);
+ *retval = NULL;
+ return 0;
+ }
+
+ ++htab->filled;
+
+ /* This is a new entry, so look up a possible callback */
+ env_callback_init(&htab->table[idx].entry);
+ /* Also look for flags */
+ env_flags_init(&htab->table[idx].entry);
+
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data, env_op_create, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+ __set_errno(EPERM);
+ *retval = NULL;
+ return 0;
+ }
+
+ /* If there is a callback, call it */
+ if (htab->table[idx].entry.callback &&
+ htab->table[idx].entry.callback(item.key, item.data,
+ env_op_create, flag)) {
+ debug("callback() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+ __set_errno(EINVAL);
+ *retval = NULL;
+ return 0;
+ }
+
+ /* return new entry */
+ *retval = &htab->table[idx].entry;
+ return 1;
+ }
+
+ __set_errno(ESRCH);
+ *retval = NULL;
+ return 0;
+}
+
+
+/*
+ * hdelete()
+ */
+
+/*
+ * The standard implementation of hsearch(3) does not provide any way
+ * to delete any entries from the hash table. We extend the code to
+ * do that.
+ */
+
+static void _hdelete(const char *key, struct hsearch_data *htab,
+ struct env_entry *ep, int idx)
+{
+ /* free used entry */
+ debug("hdelete: DELETING key \"%s\"\n", key);
+ free((void *)ep->key);
+ free(ep->data);
+ ep->callback = NULL;
+ ep->flags = 0;
+ htab->table[idx].used = USED_DELETED;
+
+ --htab->filled;
+}
+
+int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
+{
+ struct env_entry e, *ep;
+ int idx;
+
+ debug("hdelete: DELETE key \"%s\"\n", key);
+
+ e.key = (char *)key;
+
+ idx = hsearch_r(e, ENV_FIND, &ep, htab, 0);
+ if (idx == 0) {
+ __set_errno(ESRCH);
+ return 0; /* not found */
+ }
+
+ /* Check for permission */
+ if (htab->change_ok != NULL &&
+ htab->change_ok(ep, NULL, env_op_delete, flag)) {
+ debug("change_ok() rejected deleting variable "
+ "%s, skipping it!\n", key);
+ __set_errno(EPERM);
+ return 0;
+ }
+
+ /* If there is a callback, call it */
+ if (htab->table[idx].entry.callback &&
+ htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
+ debug("callback() rejected deleting variable "
+ "%s, skipping it!\n", key);
+ __set_errno(EINVAL);
+ return 0;
+ }
+
+ _hdelete(key, htab, ep, idx);
+
+ return 1;
+}
+
+#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
+/*
+ * hexport()
+ */
+
+/*
+ * Export the data stored in the hash table in linearized form.
+ *
+ * Entries are exported as "name=value" strings, separated by an
+ * arbitrary (non-NUL, of course) separator character. This allows to
+ * use this function both when formatting the U-Boot environment for
+ * external storage (using '\0' as separator), but also when using it
+ * for the "printenv" command to print all variables, simply by using
+ * as '\n" as separator. This can also be used for new features like
+ * exporting the environment data as text file, including the option
+ * for later re-import.
+ *
+ * The entries in the result list will be sorted by ascending key
+ * values.
+ *
+ * If the separator character is different from NUL, then any
+ * separator characters and backslash characters in the values will
+ * be escaped by a preceding backslash in output. This is needed for
+ * example to enable multi-line values, especially when the output
+ * shall later be parsed (for example, for re-import).
+ *
+ * There are several options how the result buffer is handled:
+ *
+ * *resp size
+ * -----------
+ * NULL 0 A string of sufficient length will be allocated.
+ * NULL >0 A string of the size given will be
+ * allocated. An error will be returned if the size is
+ * not sufficient. Any unused bytes in the string will
+ * be '\0'-padded.
+ * !NULL 0 The user-supplied buffer will be used. No length
+ * checking will be performed, i. e. it is assumed that
+ * the buffer size will always be big enough. DANGEROUS.
+ * !NULL >0 The user-supplied buffer will be used. An error will
+ * be returned if the size is not sufficient. Any unused
+ * bytes in the string will be '\0'-padded.
+ */
+
+static int cmpkey(const void *p1, const void *p2)
+{
+ struct env_entry *e1 = *(struct env_entry **)p1;
+ struct env_entry *e2 = *(struct env_entry **)p2;
+
+ return (strcmp(e1->key, e2->key));
+}
+
+static int match_string(int flag, const char *str, const char *pat, void *priv)
+{
+ switch (flag & H_MATCH_METHOD) {
+ case H_MATCH_IDENT:
+ if (strcmp(str, pat) == 0)
+ return 1;
+ break;
+ case H_MATCH_SUBSTR:
+ if (strstr(str, pat))
+ return 1;
+ break;
+#ifdef CONFIG_REGEX
+ case H_MATCH_REGEX:
+ {
+ struct slre *slrep = (struct slre *)priv;
+
+ if (slre_match(slrep, str, strlen(str), NULL))
+ return 1;
+ }
+ break;
+#endif
+ default:
+ printf("## ERROR: unsupported match method: 0x%02x\n",
+ flag & H_MATCH_METHOD);
+ break;
+ }
+ return 0;
+}
+
+static int match_entry(struct env_entry *ep, int flag, int argc,
+ char *const argv[])
+{
+ int arg;
+ void *priv = NULL;
+
+ for (arg = 0; arg < argc; ++arg) {
+#ifdef CONFIG_REGEX
+ struct slre slre;
+
+ if (slre_compile(&slre, argv[arg]) == 0) {
+ printf("Error compiling regex: %s\n", slre.err_str);
+ return 0;
+ }
+
+ priv = (void *)&slre;
+#endif
+ if (flag & H_MATCH_KEY) {
+ if (match_string(flag, ep->key, argv[arg], priv))
+ return 1;
+ }
+ if (flag & H_MATCH_DATA) {
+ if (match_string(flag, ep->data, argv[arg], priv))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
+ char **resp, size_t size,
+ int argc, char * const argv[])
+{
+ struct env_entry *list[htab->size];
+ char *res, *p;
+ size_t totlen;
+ int i, n;
+
+ /* Test for correct arguments. */
+ if ((resp == NULL) || (htab == NULL)) {
+ __set_errno(EINVAL);
+ return (-1);
+ }
+
+ debug("EXPORT table = %p, htab.size = %d, htab.filled = %d, size = %lu\n",
+ htab, htab->size, htab->filled, (ulong)size);
+ /*
+ * Pass 1:
+ * search used entries,
+ * save addresses and compute total length
+ */
+ for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) {
+
+ if (htab->table[i].used > 0) {
+ struct env_entry *ep = &htab->table[i].entry;
+ int found = match_entry(ep, flag, argc, argv);
+
+ if ((argc > 0) && (found == 0))
+ continue;
+
+ if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
+ continue;
+
+ list[n++] = ep;
+
+ totlen += strlen(ep->key);
+
+ if (sep == '\0') {
+ totlen += strlen(ep->data);
+ } else { /* check if escapes are needed */
+ char *s = ep->data;
+
+ while (*s) {
+ ++totlen;
+ /* add room for needed escape chars */
+ if ((*s == sep) || (*s == '\\'))
+ ++totlen;
+ ++s;
+ }
+ }
+ totlen += 2; /* for '=' and 'sep' char */
+ }
+ }
+
+#ifdef DEBUG
+ /* Pass 1a: print unsorted list */
+ printf("Unsorted: n=%d\n", n);
+ for (i = 0; i < n; ++i) {
+ printf("\t%3d: %p ==> %-10s => %s\n",
+ i, list[i], list[i]->key, list[i]->data);
+ }
+#endif
+
+ /* Sort list by keys */
+ qsort(list, n, sizeof(struct env_entry *), cmpkey);
+
+ /* Check if the user supplied buffer size is sufficient */
+ if (size) {
+ if (size < totlen + 1) { /* provided buffer too small */
+ printf("Env export buffer too small: %lu, but need %lu\n",
+ (ulong)size, (ulong)totlen + 1);
+ __set_errno(ENOMEM);
+ return (-1);
+ }
+ } else {
+ size = totlen + 1;
+ }
+
+ /* Check if the user provided a buffer */
+ if (*resp) {
+ /* yes; clear it */
+ res = *resp;
+ memset(res, '\0', size);
+ } else {
+ /* no, allocate and clear one */
+ *resp = res = calloc(1, size);
+ if (res == NULL) {
+ __set_errno(ENOMEM);
+ return (-1);
+ }
+ }
+ /*
+ * Pass 2:
+ * export sorted list of result data
+ */
+ for (i = 0, p = res; i < n; ++i) {
+ const char *s;
+
+ s = list[i]->key;
+ while (*s)
+ *p++ = *s++;
+ *p++ = '=';
+
+ s = list[i]->data;
+
+ while (*s) {
+ if ((*s == sep) || (*s == '\\'))
+ *p++ = '\\'; /* escape */
+ *p++ = *s++;
+ }
+ *p++ = sep;
+ }
+ *p = '\0'; /* terminate result */
+
+ return size;
+}
+#endif
+
+
+/*
+ * himport()
+ */
+
+/*
+ * Check whether variable 'name' is amongst vars[],
+ * and remove all instances by setting the pointer to NULL
+ */
+static int drop_var_from_set(const char *name, int nvars, char * vars[])
+{
+ int i = 0;
+ int res = 0;
+
+ /* No variables specified means process all of them */
+ if (nvars == 0)
+ return 1;
+
+ for (i = 0; i < nvars; i++) {
+ if (vars[i] == NULL)
+ continue;
+ /* If we found it, delete all of them */
+ if (!strcmp(name, vars[i])) {
+ vars[i] = NULL;
+ res = 1;
+ }
+ }
+ if (!res)
+ debug("Skipping non-listed variable %s\n", name);
+
+ return res;
+}
+
+/*
+ * Import linearized data into hash table.
+ *
+ * This is the inverse function to hexport(): it takes a linear list
+ * of "name=value" pairs and creates hash table entries from it.
+ *
+ * Entries without "value", i. e. consisting of only "name" or
+ * "name=", will cause this entry to be deleted from the hash table.
+ *
+ * The "flag" argument can be used to control the behaviour: when the
+ * H_NOCLEAR bit is set, then an existing hash table will kept, i. e.
+ * new data will be added to an existing hash table; otherwise, if no
+ * vars are passed, old data will be discarded and a new hash table
+ * will be created. If vars are passed, passed vars that are not in
+ * the linear list of "name=value" pairs will be removed from the
+ * current hash table.
+ *
+ * The separator character for the "name=value" pairs can be selected,
+ * so we both support importing from externally stored environment
+ * data (separated by NUL characters) and from plain text files
+ * (entries separated by newline characters).
+ *
+ * To allow for nicely formatted text input, leading white space
+ * (sequences of SPACE and TAB chars) is ignored, and entries starting
+ * (after removal of any leading white space) with a '#' character are
+ * considered comments and ignored.
+ *
+ * [NOTE: this means that a variable name cannot start with a '#'
+ * character.]
+ *
+ * When using a non-NUL separator character, backslash is used as
+ * escape character in the value part, allowing for example for
+ * multi-line values.
+ *
+ * In theory, arbitrary separator characters can be used, but only
+ * '\0' and '\n' have really been tested.
+ */
+
+int himport_r(struct hsearch_data *htab,
+ const char *env, size_t size, const char sep, int flag,
+ int crlf_is_lf, int nvars, char * const vars[])
+{
+ char *data, *sp, *dp, *name, *value;
+ char *localvars[nvars];
+ int i;
+
+ /* Test for correct arguments. */
+ if (htab == NULL) {
+ __set_errno(EINVAL);
+ return 0;
+ }
+
+ /* we allocate new space to make sure we can write to the array */
+ if ((data = malloc(size + 1)) == NULL) {
+ debug("himport_r: can't malloc %lu bytes\n", (ulong)size + 1);
+ __set_errno(ENOMEM);
+ return 0;
+ }
+ memcpy(data, env, size);
+ data[size] = '\0';
+ dp = data;
+
+ /* make a local copy of the list of variables */
+ if (nvars)
+ memcpy(localvars, vars, sizeof(vars[0]) * nvars);
+
+ if ((flag & H_NOCLEAR) == 0 && !nvars) {
+ /* Destroy old hash table if one exists */
+ debug("Destroy Hash Table: %p table = %p\n", htab,
+ htab->table);
+ if (htab->table)
+ hdestroy_r(htab);
+ }
+
+ /*
+ * Create new hash table (if needed). The computation of the hash
+ * table size is based on heuristics: in a sample of some 70+
+ * existing systems we found an average size of 39+ bytes per entry
+ * in the environment (for the whole key=value pair). Assuming a
+ * size of 8 per entry (= safety factor of ~5) should provide enough
+ * safety margin for any existing environment definitions and still
+ * allow for more than enough dynamic additions. Note that the
+ * "size" argument is supposed to give the maximum environment size
+ * (CONFIG_ENV_SIZE). This heuristics will result in
+ * unreasonably large numbers (and thus memory footprint) for
+ * big flash environments (>8,000 entries for 64 KB
+ * environment size), so we clip it to a reasonable value.
+ * On the other hand we need to add some more entries for free
+ * space when importing very small buffers. Both boundaries can
+ * be overwritten in the board config file if needed.
+ */
+
+ if (!htab->table) {
+ int nent = CONFIG_ENV_MIN_ENTRIES + size / 8;
+
+ if (nent > CONFIG_ENV_MAX_ENTRIES)
+ nent = CONFIG_ENV_MAX_ENTRIES;
+
+ debug("Create Hash Table: N=%d\n", nent);
+
+ if (hcreate_r(nent, htab) == 0) {
+ free(data);
+ return 0;
+ }
+ }
+
+ if (!size) {
+ free(data);
+ return 1; /* everything OK */
+ }
+ if(crlf_is_lf) {
+ /* Remove Carriage Returns in front of Line Feeds */
+ unsigned ignored_crs = 0;
+ for(;dp < data + size && *dp; ++dp) {
+ if(*dp == '\r' &&
+ dp < data + size - 1 && *(dp+1) == '\n')
+ ++ignored_crs;
+ else
+ *(dp-ignored_crs) = *dp;
+ }
+ size -= ignored_crs;
+ dp = data;
+ }
+ /* Parse environment; allow for '\0' and 'sep' as separators */
+ do {
+ struct env_entry e, *rv;
+
+ /* skip leading white space */
+ while (isblank(*dp))
+ ++dp;
+
+ /* skip comment lines */
+ if (*dp == '#') {
+ while (*dp && (*dp != sep))
+ ++dp;
+ ++dp;
+ continue;
+ }
+
+ /* parse name */
+ for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp)
+ ;
+
+ /* deal with "name" and "name=" entries (delete var) */
+ if (*dp == '\0' || *(dp + 1) == '\0' ||
+ *dp == sep || *(dp + 1) == sep) {
+ if (*dp == '=')
+ *dp++ = '\0';
+ *dp++ = '\0'; /* terminate name */
+
+ debug("DELETE CANDIDATE: \"%s\"\n", name);
+ if (!drop_var_from_set(name, nvars, localvars))
+ continue;
+
+ if (hdelete_r(name, htab, flag) == 0)
+ debug("DELETE ERROR ##############################\n");
+
+ continue;
+ }
+ *dp++ = '\0'; /* terminate name */
+
+ /* parse value; deal with escapes */
+ for (value = sp = dp; *dp && (*dp != sep); ++dp) {
+ if ((*dp == '\\') && *(dp + 1))
+ ++dp;
+ *sp++ = *dp;
+ }
+ *sp++ = '\0'; /* terminate value */
+ ++dp;
+
+ if (*name == 0) {
+ debug("INSERT: unable to use an empty key\n");
+ __set_errno(EINVAL);
+ free(data);
+ return 0;
+ }
+
+ /* Skip variables which are not supposed to be processed */
+ if (!drop_var_from_set(name, nvars, localvars))
+ continue;
+
+ /* enter into hash table */
+ e.key = name;
+ e.data = value;
+
+ hsearch_r(e, ENV_ENTER, &rv, htab, flag);
+ if (rv == NULL)
+ printf("himport_r: can't insert \"%s=%s\" into hash table\n",
+ name, value);
+
+ debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
+ htab, htab->filled, htab->size,
+ rv, name, value);
+ } while ((dp < data + size) && *dp); /* size check needed for text */
+ /* without '\0' termination */
+ debug("INSERT: free(data = %p)\n", data);
+ free(data);
+
+ if (flag & H_NOCLEAR)
+ goto end;
+
+ /* process variables which were not considered */
+ for (i = 0; i < nvars; i++) {
+ if (localvars[i] == NULL)
+ continue;
+ /*
+ * All variables which were not deleted from the variable list
+ * were not present in the imported env
+ * This could mean two things:
+ * a) if the variable was present in current env, we delete it
+ * b) if the variable was not present in current env, we notify
+ * it might be a typo
+ */
+ if (hdelete_r(localvars[i], htab, flag) == 0)
+ printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
+ else
+ printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
+ }
+
+end:
+ debug("INSERT: done\n");
+ return 1; /* everything OK */
+}
+
+/*
+ * hwalk_r()
+ */
+
+/*
+ * Walk all of the entries in the hash, calling the callback for each one.
+ * this allows some generic operation to be performed on each element.
+ */
+int hwalk_r(struct hsearch_data *htab, int (*callback)(struct env_entry *entry))
+{
+ int i;
+ int retval;
+
+ for (i = 1; i <= htab->size; ++i) {
+ if (htab->table[i].used > 0) {
+ retval = callback(&htab->table[i].entry);
+ if (retval)
+ return retval;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/hexdump.c b/lib/hexdump.c
new file mode 100644
index 00000000..bf14b5bd
--- /dev/null
+++ b/lib/hexdump.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * lib/hexdump.c
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <common.h>
+#include <hexdump.h>
+#include <linux/ctype.h>
+#include <linux/compat.h>
+#include <linux/log2.h>
+#include <asm/unaligned.h>
+
+const char hex_asc[] = "0123456789abcdef";
+const char hex_asc_upper[] = "0123456789ABCDEF";
+
+#ifdef CONFIG_HEXDUMP
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ * linebuf, sizeof(linebuf), true);
+ *
+ * example output buffer:
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ *
+ * Return:
+ * The amount of bytes placed in the buffer without terminating NUL. If the
+ * output was truncated, then the return value is the number of bytes
+ * (excluding the terminating NUL) which would have been written to the final
+ * string if enough space had been available.
+ */
+int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+ char *linebuf, size_t linebuflen, bool ascii)
+{
+ const u8 *ptr = buf;
+ int ngroups;
+ u8 ch;
+ int j, lx = 0;
+ int ascii_column;
+ int ret;
+
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ if (len > rowsize) /* limit to one line at a time */
+ len = rowsize;
+ if (!is_power_of_2(groupsize) || groupsize > 8)
+ groupsize = 1;
+ if ((len % groupsize) != 0) /* no mixed size output */
+ groupsize = 1;
+
+ ngroups = len / groupsize;
+ ascii_column = rowsize * 2 + rowsize / groupsize + 1;
+
+ if (!linebuflen)
+ goto overflow1;
+
+ if (!len)
+ goto nil;
+
+ if (groupsize == 8) {
+ const u64 *ptr8 = buf;
+
+ for (j = 0; j < ngroups; j++) {
+ ret = snprintf(linebuf + lx, linebuflen - lx,
+ "%s%16.16llx", j ? " " : "",
+ get_unaligned(ptr8 + j));
+ if (ret >= linebuflen - lx)
+ goto overflow1;
+ lx += ret;
+ }
+ } else if (groupsize == 4) {
+ const u32 *ptr4 = buf;
+
+ for (j = 0; j < ngroups; j++) {
+ ret = snprintf(linebuf + lx, linebuflen - lx,
+ "%s%8.8x", j ? " " : "",
+ get_unaligned(ptr4 + j));
+ if (ret >= linebuflen - lx)
+ goto overflow1;
+ lx += ret;
+ }
+ } else if (groupsize == 2) {
+ const u16 *ptr2 = buf;
+
+ for (j = 0; j < ngroups; j++) {
+ ret = snprintf(linebuf + lx, linebuflen - lx,
+ "%s%4.4x", j ? " " : "",
+ get_unaligned(ptr2 + j));
+ if (ret >= linebuflen - lx)
+ goto overflow1;
+ lx += ret;
+ }
+ } else {
+ for (j = 0; j < len; j++) {
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ ch = ptr[j];
+ linebuf[lx++] = hex_asc_hi(ch);
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ linebuf[lx++] = hex_asc_lo(ch);
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ linebuf[lx++] = ' ';
+ }
+ if (j)
+ lx--;
+ }
+ if (!ascii)
+ goto nil;
+
+ while (lx < ascii_column) {
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ linebuf[lx++] = ' ';
+ }
+ for (j = 0; j < len; j++) {
+ if (linebuflen < lx + 2)
+ goto overflow2;
+ ch = ptr[j];
+ linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
+ }
+nil:
+ linebuf[lx] = '\0';
+ return lx;
+overflow2:
+ linebuf[lx++] = '\0';
+overflow1:
+ return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
+}
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the stdio, with an optional leading prefix.
+ *
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
+ * E.g.:
+ * print_hex_dump("raw data: ", DUMP_PREFIX_ADDRESS, 16, 1, frame->data,
+ * frame->len, true);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
+ */
+void print_hex_dump(const char *prefix_str, int prefix_type, int rowsize,
+ int groupsize, const void *buf, size_t len, bool ascii)
+{
+ const u8 *ptr = buf;
+ int i, linelen, remaining = len;
+ char linebuf[32 * 3 + 2 + 32 + 1];
+
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ for (i = 0; i < len; i += rowsize) {
+ linelen = min(remaining, rowsize);
+ remaining -= rowsize;
+
+ hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+ linebuf, sizeof(linebuf), ascii);
+
+ switch (prefix_type) {
+ case DUMP_PREFIX_ADDRESS:
+ printf("%s%p: %s\n", prefix_str, ptr + i, linebuf);
+ break;
+ case DUMP_PREFIX_OFFSET:
+ printf("%s%.8x: %s\n", prefix_str, i, linebuf);
+ break;
+ default:
+ printf("%s%s\n", prefix_str, linebuf);
+ break;
+ }
+ }
+}
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), rowsize of 16, groupsize of 1,
+ * and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ const void *buf, size_t len)
+{
+ print_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true);
+}
+#else
+/*
+ * Some code in U-Boot copy-pasted from Linux kernel uses both
+ * functions below so to keep stuff compilable we keep these stubs here.
+ */
+void print_hex_dump(const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize, const void *buf,
+ size_t len, bool ascii)
+{
+}
+
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ const void *buf, size_t len)
+{
+}
+#endif /* CONFIG_HEXDUMP */
diff --git a/lib/image-sparse.c b/lib/image-sparse.c
new file mode 100644
index 00000000..03606213
--- /dev/null
+++ b/lib/image-sparse.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ * Portions Copyright 2014 Broadcom Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of The Linux Foundation 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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.
+ *
+ * NOTE:
+ * Although it is very similar, this license text is not identical
+ * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
+ */
+
+#include <config.h>
+#include <common.h>
+#include <image-sparse.h>
+#include <div64.h>
+#include <malloc.h>
+#include <part.h>
+#include <sparse_format.h>
+
+#include <linux/math64.h>
+
+static void default_log(const char *ignored, char *response) {}
+
+int write_sparse_image(struct sparse_storage *info,
+ const char *part_name, void *data, char *response)
+{
+ lbaint_t blk;
+ lbaint_t blkcnt;
+ lbaint_t blks;
+ uint32_t bytes_written = 0;
+ unsigned int chunk;
+ unsigned int offset;
+ unsigned int chunk_data_sz;
+ uint32_t *fill_buf = NULL;
+ uint32_t fill_val;
+ sparse_header_t *sparse_header;
+ chunk_header_t *chunk_header;
+ uint32_t total_blocks = 0;
+ int fill_buf_num_blks;
+ int i;
+ int j;
+
+ fill_buf_num_blks = CONFIG_IMAGE_SPARSE_FILLBUF_SIZE / info->blksz;
+
+ /* Read and skip over sparse image header */
+ sparse_header = (sparse_header_t *)data;
+
+ data += sparse_header->file_hdr_sz;
+ if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) {
+ /*
+ * Skip the remaining bytes in a header that is longer than
+ * we expected.
+ */
+ data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
+ }
+
+ if (!info->mssg)
+ info->mssg = default_log;
+
+ debug("=== Sparse Image Header ===\n");
+ debug("magic: 0x%x\n", sparse_header->magic);
+ debug("major_version: 0x%x\n", sparse_header->major_version);
+ debug("minor_version: 0x%x\n", sparse_header->minor_version);
+ debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
+ debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
+ debug("blk_sz: %d\n", sparse_header->blk_sz);
+ debug("total_blks: %d\n", sparse_header->total_blks);
+ debug("total_chunks: %d\n", sparse_header->total_chunks);
+
+ /*
+ * Verify that the sparse block size is a multiple of our
+ * storage backend block size
+ */
+ div_u64_rem(sparse_header->blk_sz, info->blksz, &offset);
+ if (offset) {
+ printf("%s: Sparse image block size issue [%u]\n",
+ __func__, sparse_header->blk_sz);
+ info->mssg("sparse image block size issue", response);
+ return -1;
+ }
+
+ puts("Flashing Sparse Image\n");
+
+ /* Start processing chunks */
+ blk = info->start;
+ for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
+ /* Read and skip over chunk header */
+ chunk_header = (chunk_header_t *)data;
+ data += sizeof(chunk_header_t);
+
+ if (chunk_header->chunk_type != CHUNK_TYPE_RAW) {
+ debug("=== Chunk Header ===\n");
+ debug("chunk_type: 0x%x\n", chunk_header->chunk_type);
+ debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
+ debug("total_size: 0x%x\n", chunk_header->total_sz);
+ }
+
+ if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) {
+ /*
+ * Skip the remaining bytes in a header that is longer
+ * than we expected.
+ */
+ data += (sparse_header->chunk_hdr_sz -
+ sizeof(chunk_header_t));
+ }
+
+ chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
+ blkcnt = chunk_data_sz / info->blksz;
+ switch (chunk_header->chunk_type) {
+ case CHUNK_TYPE_RAW:
+ if (chunk_header->total_sz !=
+ (sparse_header->chunk_hdr_sz + chunk_data_sz)) {
+ info->mssg("Bogus chunk size for chunk type Raw",
+ response);
+ return -1;
+ }
+
+ if (blk + blkcnt > info->start + info->size) {
+ printf(
+ "%s: Request would exceed partition size!\n",
+ __func__);
+ info->mssg("Request would exceed partition size!",
+ response);
+ return -1;
+ }
+
+ blks = info->write(info, blk, blkcnt, data);
+ /* blks might be > blkcnt (eg. NAND bad-blocks) */
+ if (blks < blkcnt) {
+ printf("%s: %s" LBAFU " [" LBAFU "]\n",
+ __func__, "Write failed, block #",
+ blk, blks);
+ info->mssg("flash write failure", response);
+ return -1;
+ }
+ blk += blks;
+ bytes_written += blkcnt * info->blksz;
+ total_blocks += chunk_header->chunk_sz;
+ data += chunk_data_sz;
+ break;
+
+ case CHUNK_TYPE_FILL:
+ if (chunk_header->total_sz !=
+ (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) {
+ info->mssg("Bogus chunk size for chunk type FILL", response);
+ return -1;
+ }
+
+ fill_buf = (uint32_t *)
+ memalign(ARCH_DMA_MINALIGN,
+ ROUNDUP(
+ info->blksz * fill_buf_num_blks,
+ ARCH_DMA_MINALIGN));
+ if (!fill_buf) {
+ info->mssg("Malloc failed for: CHUNK_TYPE_FILL",
+ response);
+ return -1;
+ }
+
+ fill_val = *(uint32_t *)data;
+ data = (char *)data + sizeof(uint32_t);
+
+ for (i = 0;
+ i < (info->blksz * fill_buf_num_blks /
+ sizeof(fill_val));
+ i++)
+ fill_buf[i] = fill_val;
+
+ if (blk + blkcnt > info->start + info->size) {
+ printf(
+ "%s: Request would exceed partition size!\n",
+ __func__);
+ info->mssg("Request would exceed partition size!",
+ response);
+ return -1;
+ }
+
+ for (i = 0; i < blkcnt;) {
+ j = blkcnt - i;
+ if (j > fill_buf_num_blks)
+ j = fill_buf_num_blks;
+ blks = info->write(info, blk, j, fill_buf);
+ /* blks might be > j (eg. NAND bad-blocks) */
+ if (blks < j) {
+ printf("%s: %s " LBAFU " [%d]\n",
+ __func__,
+ "Write failed, block #",
+ blk, j);
+ info->mssg("flash write failure",
+ response);
+ free(fill_buf);
+ return -1;
+ }
+ blk += blks;
+ i += j;
+ }
+ bytes_written += blkcnt * info->blksz;
+ total_blocks += chunk_data_sz / sparse_header->blk_sz;
+ free(fill_buf);
+ break;
+
+ case CHUNK_TYPE_DONT_CARE:
+ blk += info->reserve(info, blk, blkcnt);
+ total_blocks += chunk_header->chunk_sz;
+ break;
+
+ case CHUNK_TYPE_CRC32:
+ if (chunk_header->total_sz !=
+ sparse_header->chunk_hdr_sz) {
+ info->mssg("Bogus chunk size for chunk type Dont Care",
+ response);
+ return -1;
+ }
+ total_blocks += chunk_header->chunk_sz;
+ data += chunk_data_sz;
+ break;
+
+ default:
+ printf("%s: Unknown chunk type: %x\n", __func__,
+ chunk_header->chunk_type);
+ info->mssg("Unknown chunk type", response);
+ return -1;
+ }
+ }
+
+ debug("Wrote %d blocks, expected to write %d blocks\n",
+ total_blocks, sparse_header->total_blks);
+ printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
+
+ if (total_blocks != sparse_header->total_blks) {
+ info->mssg("sparse image write failure", response);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/lib/ldiv.c b/lib/ldiv.c
new file mode 100644
index 00000000..5b1a25f2
--- /dev/null
+++ b/lib/ldiv.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ */
+
+typedef struct {
+ long quot;
+ long rem;
+} ldiv_t;
+/* Return the `ldiv_t' representation of NUMER over DENOM. */
+ldiv_t
+ldiv (long int numer, long int denom)
+{
+ ldiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where
+ NUMER / DENOM is to be computed in infinite precision. In
+ other words, we should always truncate the quotient towards
+ zero, never -infinity. Machine division and remainer may
+ work either way when one or both of NUMER or DENOM is
+ negative. If only one is negative and QUOT has been
+ truncated towards -infinity, REM will have the same sign as
+ DENOM and the opposite sign of NUMER; if both are negative
+ and QUOT has been truncated towards -infinity, REM will be
+ positive (will have the opposite sign of NUMER). These are
+ considered `wrong'. If both are NUM and DENOM are positive,
+ RESULT will always be positive. This all boils down to: if
+ NUMER >= 0, but REM < 0, we got the wrong answer. In that
+ case, to get the right answer, add 1 to QUOT and subtract
+ DENOM from REM. */
+
+ if (numer >= 0 && result.rem < 0)
+ {
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
diff --git a/lib/libavb/Makefile b/lib/libavb/Makefile
new file mode 100644
index 00000000..b983fe76
--- /dev/null
+++ b/lib/libavb/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2017 Linaro Limited
+
+obj-$(CONFIG_LIBAVB) += avb_chain_partition_descriptor.o avb_cmdline.o
+obj-$(CONFIG_LIBAVB) += avb_crypto.o avb_footer.o avb_hashtree_descriptor.o
+obj-$(CONFIG_LIBAVB) += avb_property_descriptor.o avb_sha256.o
+obj-$(CONFIG_LIBAVB) += avb_slot_verify.o avb_util.o avb_version.o
+obj-$(CONFIG_LIBAVB) += avb_descriptor.o avb_hash_descriptor.o
+obj-$(CONFIG_LIBAVB) += avb_kernel_cmdline_descriptor.o avb_rsa.o avb_sha512.o
+obj-$(CONFIG_LIBAVB) += avb_sysdeps_posix.o avb_vbmeta_image.o
+
+ccflags-y = -DAVB_COMPILATION
diff --git a/lib/libavb/avb_chain_partition_descriptor.c b/lib/libavb/avb_chain_partition_descriptor.c
new file mode 100644
index 00000000..e2993063
--- /dev/null
+++ b/lib/libavb/avb_chain_partition_descriptor.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_chain_partition_descriptor.h"
+#include "avb_util.h"
+
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+ const AvbChainPartitionDescriptor* src, AvbChainPartitionDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbChainPartitionDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) {
+ avb_error("Invalid tag for chain partition descriptor.\n");
+ return false;
+ }
+
+ dest->rollback_index_location = avb_be32toh(dest->rollback_index_location);
+ dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+ dest->public_key_len = avb_be32toh(dest->public_key_len);
+
+ if (dest->rollback_index_location < 1) {
+ avb_error("Invalid rollback index location value.\n");
+ return false;
+ }
+
+ /* Check that partition_name and public_key are fully contained. */
+ expected_size = sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->public_key_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/lib/libavb/avb_chain_partition_descriptor.h b/lib/libavb/avb_chain_partition_descriptor.h
new file mode 100644
index 00000000..80e22717
--- /dev/null
+++ b/lib/libavb/avb_chain_partition_descriptor.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+#define AVB_CHAIN_PARTITION_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor containing a pointer to signed integrity data stored
+ * on another partition. The descriptor contains the partition name in
+ * question (without the A/B suffix), the public key used to sign the
+ * integrity data, and rollback index location to use for rollback
+ * protection.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded) and |public_key_len| bytes of the
+ * public key.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ */
+typedef struct AvbChainPartitionDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint32_t rollback_index_location;
+ uint32_t partition_name_len;
+ uint32_t public_key_len;
+ uint8_t reserved[64];
+} AVB_ATTR_PACKED AvbChainPartitionDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_chain_partition_descriptor_validate_and_byteswap(
+ const AvbChainPartitionDescriptor* src,
+ AvbChainPartitionDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CHAIN_PARTITION_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_cmdline.c b/lib/libavb/avb_cmdline.c
new file mode 100644
index 00000000..684c512b
--- /dev/null
+++ b/lib/libavb/avb_cmdline.c
@@ -0,0 +1,459 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_cmdline.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_version.h"
+
+#define NUM_GUIDS 3
+
+/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
+ * values. Returns NULL on OOM, otherwise the cmdline with values
+ * replaced.
+ */
+char* avb_sub_cmdline(AvbOps* ops,
+ const char* cmdline,
+ const char* ab_suffix,
+ bool using_boot_for_vbmeta,
+ const AvbCmdlineSubstList* additional_substitutions) {
+ const char* part_name_str[NUM_GUIDS] = {"system", "boot", "vbmeta"};
+ const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
+ "$(ANDROID_BOOT_PARTUUID)",
+ "$(ANDROID_VBMETA_PARTUUID)"};
+ char* ret = NULL;
+ AvbIOResult io_ret;
+ size_t n;
+
+ /* Special-case for when the top-level vbmeta struct is in the boot
+ * partition.
+ */
+ if (using_boot_for_vbmeta) {
+ part_name_str[2] = "boot";
+ }
+
+ /* Replace unique partition GUIDs */
+ for (n = 0; n < NUM_GUIDS; n++) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ char guid_buf[37];
+
+ /* Don't attempt to query the partition guid unless its search string is
+ * present in the command line. Note: the original cmdline is used here,
+ * not the replaced one. See b/116010959.
+ */
+ if (avb_strstr(cmdline, replace_str[n]) == NULL) {
+ continue;
+ }
+
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ part_name_str[n],
+ avb_strlen(part_name_str[n]),
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ goto fail;
+ }
+
+ io_ret = ops->get_unique_guid_for_partition(
+ ops, part_name, guid_buf, sizeof guid_buf);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ goto fail;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting unique GUID for partition.\n");
+ goto fail;
+ }
+
+ if (ret == NULL) {
+ ret = avb_replace(cmdline, replace_str[n], guid_buf);
+ } else {
+ char* new_ret = avb_replace(ret, replace_str[n], guid_buf);
+ avb_free(ret);
+ ret = new_ret;
+ }
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+
+ /* It's possible there is no _PARTUUID for replacement above.
+ * Duplicate cmdline to ret for additional substitutions below.
+ */
+ if (ret == NULL) {
+ ret = avb_strdup(cmdline);
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+
+ /* Replace any additional substitutions. */
+ if (additional_substitutions != NULL) {
+ for (n = 0; n < additional_substitutions->size; ++n) {
+ char* new_ret = avb_replace(ret,
+ additional_substitutions->tokens[n],
+ additional_substitutions->values[n]);
+ avb_free(ret);
+ ret = new_ret;
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+ }
+
+ return ret;
+
+fail:
+ if (ret != NULL) {
+ avb_free(ret);
+ }
+ return NULL;
+}
+
+static int cmdline_append_option(AvbSlotVerifyData* slot_data,
+ const char* key,
+ const char* value) {
+ size_t offset, key_len, value_len;
+ char* new_cmdline;
+
+ key_len = avb_strlen(key);
+ value_len = avb_strlen(value);
+
+ offset = 0;
+ if (slot_data->cmdline != NULL) {
+ offset = avb_strlen(slot_data->cmdline);
+ if (offset > 0) {
+ offset += 1;
+ }
+ }
+
+ new_cmdline = avb_calloc(offset + key_len + value_len + 2);
+ if (new_cmdline == NULL) {
+ return 0;
+ }
+ if (offset > 0) {
+ avb_memcpy(new_cmdline, slot_data->cmdline, offset - 1);
+ new_cmdline[offset - 1] = ' ';
+ }
+ avb_memcpy(new_cmdline + offset, key, key_len);
+ new_cmdline[offset + key_len] = '=';
+ avb_memcpy(new_cmdline + offset + key_len + 1, value, value_len);
+ if (slot_data->cmdline != NULL) {
+ avb_free(slot_data->cmdline);
+ }
+ slot_data->cmdline = new_cmdline;
+
+ return 1;
+}
+
+#define AVB_MAX_DIGITS_UINT64 32
+
+/* Writes |value| to |digits| in base 10 followed by a NUL byte.
+ * Returns number of characters written excluding the NUL byte.
+ */
+static size_t uint64_to_base10(uint64_t value,
+ char digits[AVB_MAX_DIGITS_UINT64]) {
+ char rev_digits[AVB_MAX_DIGITS_UINT64];
+ size_t n, num_digits;
+
+ for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
+ rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
+ if (value == 0) {
+ break;
+ }
+ }
+
+ for (n = 0; n < num_digits; n++) {
+ digits[n] = rev_digits[num_digits - 1 - n];
+ }
+ digits[n] = '\0';
+ return n;
+}
+
+static int cmdline_append_version(AvbSlotVerifyData* slot_data,
+ const char* key,
+ uint64_t major_version,
+ uint64_t minor_version) {
+ char major_digits[AVB_MAX_DIGITS_UINT64];
+ char minor_digits[AVB_MAX_DIGITS_UINT64];
+ char combined[AVB_MAX_DIGITS_UINT64 * 2 + 1];
+ size_t num_major_digits, num_minor_digits;
+
+ num_major_digits = uint64_to_base10(major_version, major_digits);
+ num_minor_digits = uint64_to_base10(minor_version, minor_digits);
+ avb_memcpy(combined, major_digits, num_major_digits);
+ combined[num_major_digits] = '.';
+ avb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
+ combined[num_major_digits + 1 + num_minor_digits] = '\0';
+
+ return cmdline_append_option(slot_data, key, combined);
+}
+
+static int cmdline_append_uint64_base10(AvbSlotVerifyData* slot_data,
+ const char* key,
+ uint64_t value) {
+ char digits[AVB_MAX_DIGITS_UINT64];
+ uint64_to_base10(value, digits);
+ return cmdline_append_option(slot_data, key, digits);
+}
+
+static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
+ const char* key,
+ const uint8_t* data,
+ size_t data_len) {
+ int ret;
+ char* hex_data = avb_bin2hex(data, data_len);
+ if (hex_data == NULL) {
+ return 0;
+ }
+ ret = cmdline_append_option(slot_data, key, hex_data);
+ avb_free(hex_data);
+ return ret;
+}
+
+AvbSlotVerifyResult avb_append_options(
+ AvbOps* ops,
+ AvbSlotVerifyFlags flags,
+ AvbSlotVerifyData* slot_data,
+ AvbVBMetaImageHeader* toplevel_vbmeta,
+ AvbAlgorithmType algorithm_type,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbHashtreeErrorMode resolved_hashtree_error_mode) {
+ AvbSlotVerifyResult ret;
+ const char* verity_mode;
+ bool is_device_unlocked;
+ AvbIOResult io_ret;
+
+ /* Add androidboot.vbmeta.device option... except if not using a vbmeta
+ * partition since it doesn't make sense in that case.
+ */
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device",
+ "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+
+ /* Add androidboot.vbmeta.avb_version option. */
+ if (!cmdline_append_version(slot_data,
+ "androidboot.vbmeta.avb_version",
+ AVB_VERSION_MAJOR,
+ AVB_VERSION_MINOR)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ /* Set androidboot.avb.device_state to "locked" or "unlocked". */
+ io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting device state.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device_state",
+ is_device_unlocked ? "unlocked" : "locked")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ /* Set androidboot.vbmeta.{hash_alg, size, digest} - use same hash
+ * function as is used to sign vbmeta.
+ */
+ switch (algorithm_type) {
+ /* Explicit fallthrough. */
+ case AVB_ALGORITHM_TYPE_NONE:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA8192: {
+ size_t n, total_size = 0;
+ uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
+ for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+ total_size += slot_data->vbmeta_images[n].vbmeta_size;
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.hash_alg", "sha256") ||
+ !cmdline_append_uint64_base10(
+ slot_data, "androidboot.vbmeta.size", total_size) ||
+ !cmdline_append_hex(slot_data,
+ "androidboot.vbmeta.digest",
+ vbmeta_digest,
+ AVB_SHA256_DIGEST_SIZE)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ } break;
+ /* Explicit fallthrough. */
+ case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA8192: {
+ size_t n, total_size = 0;
+ uint8_t vbmeta_digest[AVB_SHA512_DIGEST_SIZE];
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ slot_data, AVB_DIGEST_TYPE_SHA512, vbmeta_digest);
+ for (n = 0; n < slot_data->num_vbmeta_images; n++) {
+ total_size += slot_data->vbmeta_images[n].vbmeta_size;
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.hash_alg", "sha512") ||
+ !cmdline_append_uint64_base10(
+ slot_data, "androidboot.vbmeta.size", total_size) ||
+ !cmdline_append_hex(slot_data,
+ "androidboot.vbmeta.digest",
+ vbmeta_digest,
+ AVB_SHA512_DIGEST_SIZE)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ } break;
+ case _AVB_ALGORITHM_NUM_TYPES:
+ avb_assert_not_reached();
+ break;
+ }
+
+ /* Set androidboot.veritymode and androidboot.vbmeta.invalidate_on_error */
+ if (toplevel_vbmeta->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+ verity_mode = "disabled";
+ } else {
+ const char* dm_verity_mode;
+ char* new_ret;
+
+ switch (resolved_hashtree_error_mode) {
+ case AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE:
+ if (!cmdline_append_option(
+ slot_data, "androidboot.vbmeta.invalidate_on_error", "yes")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ verity_mode = "enforcing";
+ dm_verity_mode = "restart_on_corruption";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_RESTART:
+ verity_mode = "enforcing";
+ dm_verity_mode = "restart_on_corruption";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_EIO:
+ verity_mode = "eio";
+ /* For now there's no option to specify the EIO mode. So
+ * just use 'ignore_zero_blocks' since that's already set
+ * and dm-verity-target.c supports specifying this multiple
+ * times.
+ */
+ dm_verity_mode = "ignore_zero_blocks";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_LOGGING:
+ verity_mode = "logging";
+ dm_verity_mode = "ignore_corruption";
+ break;
+ case AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO:
+ // Should never get here because MANAGED_RESTART_AND_EIO is
+ // remapped by avb_manage_hashtree_error_mode().
+ avb_assert_not_reached();
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto out;
+ default:
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto out;
+ }
+ new_ret = avb_replace(
+ slot_data->cmdline, "$(ANDROID_VERITY_MODE)", dm_verity_mode);
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_ret;
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+ if (!cmdline_append_option(
+ slot_data, "androidboot.veritymode", verity_mode)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
+ if (!cmdline_append_option(
+ slot_data, "androidboot.veritymode.managed", "yes")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+
+ return ret;
+}
+
+AvbCmdlineSubstList* avb_new_cmdline_subst_list() {
+ return (AvbCmdlineSubstList*)avb_calloc(sizeof(AvbCmdlineSubstList));
+}
+
+void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst) {
+ size_t i;
+ for (i = 0; i < cmdline_subst->size; ++i) {
+ avb_free(cmdline_subst->tokens[i]);
+ avb_free(cmdline_subst->values[i]);
+ }
+ cmdline_subst->size = 0;
+ avb_free(cmdline_subst);
+}
+
+AvbSlotVerifyResult avb_add_root_digest_substitution(
+ const char* part_name,
+ const uint8_t* digest,
+ size_t digest_size,
+ AvbCmdlineSubstList* out_cmdline_subst) {
+ const char* kDigestSubPrefix = "$(AVB_";
+ const char* kDigestSubSuffix = "_ROOT_DIGEST)";
+ size_t part_name_len = avb_strlen(part_name);
+ size_t list_index = out_cmdline_subst->size;
+
+ avb_assert(part_name_len < AVB_PART_NAME_MAX_SIZE);
+ avb_assert(digest_size <= AVB_SHA512_DIGEST_SIZE);
+ if (part_name_len >= AVB_PART_NAME_MAX_SIZE ||
+ digest_size > AVB_SHA512_DIGEST_SIZE) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ if (out_cmdline_subst->size >= AVB_MAX_NUM_CMDLINE_SUBST) {
+ /* The list is full. Currently dynamic growth of this list is not supported.
+ */
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ /* Construct the token to replace in the command line based on the partition
+ * name. For partition 'foo', this will be '$(AVB_FOO_ROOT_DIGEST)'.
+ */
+ out_cmdline_subst->tokens[list_index] =
+ avb_strdupv(kDigestSubPrefix, part_name, kDigestSubSuffix, NULL);
+ if (out_cmdline_subst->tokens[list_index] == NULL) {
+ goto fail;
+ }
+ avb_uppercase(out_cmdline_subst->tokens[list_index]);
+
+ /* The digest value is hex encoded when inserted in the command line. */
+ out_cmdline_subst->values[list_index] = avb_bin2hex(digest, digest_size);
+ if (out_cmdline_subst->values[list_index] == NULL) {
+ goto fail;
+ }
+
+ out_cmdline_subst->size++;
+ return AVB_SLOT_VERIFY_RESULT_OK;
+
+fail:
+ if (out_cmdline_subst->tokens[list_index]) {
+ avb_free(out_cmdline_subst->tokens[list_index]);
+ }
+ if (out_cmdline_subst->values[list_index]) {
+ avb_free(out_cmdline_subst->values[list_index]);
+ }
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+}
diff --git a/lib/libavb/avb_cmdline.h b/lib/libavb/avb_cmdline.h
new file mode 100644
index 00000000..96539d84
--- /dev/null
+++ b/lib/libavb/avb_cmdline.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_sha.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_CMDLINE_H_
+#define AVB_CMDLINE_H_
+
+#include "avb_ops.h"
+#include "avb_slot_verify.h"
+
+/* Maximum allow length (in bytes) of a partition name, including
+ * ab_suffix.
+ */
+#define AVB_PART_NAME_MAX_SIZE 32
+
+#define AVB_MAX_NUM_CMDLINE_SUBST 10
+
+/* Holds information about command-line substitutions. */
+typedef struct AvbCmdlineSubstList {
+ size_t size;
+ char* tokens[AVB_MAX_NUM_CMDLINE_SUBST];
+ char* values[AVB_MAX_NUM_CMDLINE_SUBST];
+} AvbCmdlineSubstList;
+
+/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
+ * values. Returns NULL on OOM, otherwise the cmdline with values
+ * replaced.
+ */
+char* avb_sub_cmdline(AvbOps* ops,
+ const char* cmdline,
+ const char* ab_suffix,
+ bool using_boot_for_vbmeta,
+ const AvbCmdlineSubstList* additional_substitutions);
+
+AvbSlotVerifyResult avb_append_options(
+ AvbOps* ops,
+ AvbSlotVerifyFlags flags,
+ AvbSlotVerifyData* slot_data,
+ AvbVBMetaImageHeader* toplevel_vbmeta,
+ AvbAlgorithmType algorithm_type,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbHashtreeErrorMode resolved_hashtree_error_mode);
+
+/* Allocates and initializes a new command line substitution list. Free with
+ * |avb_free_cmdline_subst_list|.
+ */
+AvbCmdlineSubstList* avb_new_cmdline_subst_list(void);
+
+/* Use this instead of |avb_free| to deallocate a AvbCmdlineSubstList. */
+void avb_free_cmdline_subst_list(AvbCmdlineSubstList* cmdline_subst);
+
+/* Adds a hashtree root digest to be substituted in $(AVB_*_ROOT_DIGEST)
+ * variables. The partition name differentiates the variable. For example, if
+ * |part_name| is "foo" then $(AVB_FOO_ROOT_DIGEST) will be substituted with the
+ * hex encoding of the digest. The substitution will be added to
+ * |out_cmdline_subst|. Returns AVB_SLOT_VERIFY_RESULT_OK on success.
+ */
+AvbSlotVerifyResult avb_add_root_digest_substitution(
+ const char* part_name,
+ const uint8_t* digest,
+ size_t digest_size,
+ AvbCmdlineSubstList* out_cmdline_subst);
+
+#endif
diff --git a/lib/libavb/avb_crypto.c b/lib/libavb/avb_crypto.c
new file mode 100644
index 00000000..f1836d5f
--- /dev/null
+++ b/lib/libavb/avb_crypto.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+
+/* NOTE: The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is
+ * obtained from section 5.2.2 of RFC 4880.
+ */
+
+static const uint8_t
+ padding_RSA2048_SHA256[AVB_RSA2048_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA4096_SHA256[AVB_RSA4096_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA8192_SHA256[AVB_RSA8192_NUM_BYTES - AVB_SHA256_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+
+static const uint8_t
+ padding_RSA2048_SHA512[AVB_RSA2048_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+ padding_RSA4096_SHA512[AVB_RSA4096_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30,
+ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40};
+
+static const uint8_t
+ padding_RSA8192_SHA512[AVB_RSA8192_NUM_BYTES - AVB_SHA512_DIGEST_SIZE] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+static AvbAlgorithmData algorithm_data[_AVB_ALGORITHM_NUM_TYPES] = {
+ /* AVB_ALGORITHM_TYPE_NONE */
+ {.padding = NULL, .padding_len = 0, .hash_len = 0},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA2048 */
+ {.padding = padding_RSA2048_SHA256,
+ .padding_len = sizeof(padding_RSA2048_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA4096 */
+ {.padding = padding_RSA4096_SHA256,
+ .padding_len = sizeof(padding_RSA4096_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA256_RSA8192 */
+ {.padding = padding_RSA8192_SHA256,
+ .padding_len = sizeof(padding_RSA8192_SHA256),
+ .hash_len = AVB_SHA256_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA2048 */
+ {.padding = padding_RSA2048_SHA512,
+ .padding_len = sizeof(padding_RSA2048_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA4096 */
+ {.padding = padding_RSA4096_SHA512,
+ .padding_len = sizeof(padding_RSA4096_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+ /* AVB_ALGORITHM_TYPE_SHA512_RSA8192 */
+ {.padding = padding_RSA8192_SHA512,
+ .padding_len = sizeof(padding_RSA8192_SHA512),
+ .hash_len = AVB_SHA512_DIGEST_SIZE},
+};
+
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm) {
+ if ((size_t)algorithm < _AVB_ALGORITHM_NUM_TYPES) {
+ return &algorithm_data[algorithm];
+ }
+ return NULL;
+}
+
+bool avb_rsa_public_key_header_validate_and_byteswap(
+ const AvbRSAPublicKeyHeader* src, AvbRSAPublicKeyHeader* dest) {
+ avb_memcpy(dest, src, sizeof(AvbRSAPublicKeyHeader));
+
+ dest->key_num_bits = avb_be32toh(dest->key_num_bits);
+ dest->n0inv = avb_be32toh(dest->n0inv);
+
+ return true;
+}
diff --git a/lib/libavb/avb_crypto.h b/lib/libavb/avb_crypto.h
new file mode 100644
index 00000000..d8f649b1
--- /dev/null
+++ b/lib/libavb/avb_crypto.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_CRYPTO_H_
+#define AVB_CRYPTO_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Size of a RSA-2048 signature. */
+#define AVB_RSA2048_NUM_BYTES 256
+
+/* Size of a RSA-4096 signature. */
+#define AVB_RSA4096_NUM_BYTES 512
+
+/* Size of a RSA-8192 signature. */
+#define AVB_RSA8192_NUM_BYTES 1024
+
+/* Size in bytes of a SHA-1 digest. */
+#define AVB_SHA1_DIGEST_SIZE 20
+
+/* Size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_DIGEST_SIZE 32
+
+/* Size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_DIGEST_SIZE 64
+
+/* Possible digest types supported by libavb routines. */
+typedef enum {
+ AVB_DIGEST_TYPE_SHA256,
+ AVB_DIGEST_TYPE_SHA512,
+} AvbDigestType;
+
+/* Algorithms that can be used in the vbmeta image for
+ * verification. An algorithm consists of a hash type and a signature
+ * type.
+ *
+ * The data used to calculate the hash is the three blocks mentioned
+ * in the documentation for |AvbVBMetaImageHeader| except for the data
+ * in the "Authentication data" block.
+ *
+ * For signatures with RSA keys, PKCS v1.5 padding is used. The public
+ * key data is stored in the auxiliary data block, see
+ * |AvbRSAPublicKeyHeader| for the serialization format.
+ *
+ * Each algorithm type is described below:
+ *
+ * AVB_ALGORITHM_TYPE_NONE: There is no hash, no signature of the
+ * data, and no public key. The data cannot be verified. The fields
+ * |hash_size|, |signature_size|, and |public_key_size| must be zero.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA2048: The hash function used is
+ * SHA-256, resulting in 32 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 32,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA256_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA2048: The hash function used is
+ * SHA-512, resulting in 64 bytes of hash digest data. This hash is
+ * signed with a 2048-bit RSA key. The field |hash_size| must be 64,
+ * |signature_size| must be 256, and the public key data must have
+ * |key_num_bits| set to 2048.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA4096: Like above, but only with
+ * a 4096-bit RSA key and |signature_size| set to 512.
+ *
+ * AVB_ALGORITHM_TYPE_SHA512_RSA8192: Like above, but only with
+ * a 8192-bit RSA key and |signature_size| set to 1024.
+ */
+typedef enum {
+ AVB_ALGORITHM_TYPE_NONE,
+ AVB_ALGORITHM_TYPE_SHA256_RSA2048,
+ AVB_ALGORITHM_TYPE_SHA256_RSA4096,
+ AVB_ALGORITHM_TYPE_SHA256_RSA8192,
+ AVB_ALGORITHM_TYPE_SHA512_RSA2048,
+ AVB_ALGORITHM_TYPE_SHA512_RSA4096,
+ AVB_ALGORITHM_TYPE_SHA512_RSA8192,
+ _AVB_ALGORITHM_NUM_TYPES
+} AvbAlgorithmType;
+
+/* Holds algorithm-specific data. The |padding| is needed by avb_rsa_verify. */
+typedef struct {
+ const uint8_t* padding;
+ size_t padding_len;
+ size_t hash_len;
+} AvbAlgorithmData;
+
+/* Provides algorithm-specific data for a given |algorithm|. Returns NULL if
+ * |algorithm| is invalid.
+ */
+const AvbAlgorithmData* avb_get_algorithm_data(AvbAlgorithmType algorithm)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* The header for a serialized RSA public key.
+ *
+ * The size of the key is given by |key_num_bits|, for example 2048
+ * for a RSA-2048 key. By definition, a RSA public key is the pair (n,
+ * e) where |n| is the modulus (which can be represented in
+ * |key_num_bits| bits) and |e| is the public exponent. The exponent
+ * is not stored since it's assumed to always be 65537.
+ *
+ * To optimize verification, the key block includes two precomputed
+ * values, |n0inv| (fits in 32 bits) and |rr| and can always be
+ * represented in |key_num_bits|.
+
+ * The value |n0inv| is the value -1/n[0] (mod 2^32). The value |rr|
+ * is (2^key_num_bits)^2 (mod n).
+ *
+ * Following this header is |key_num_bits| bits of |n|, then
+ * |key_num_bits| bits of |rr|. Both values are stored with most
+ * significant bit first. Each serialized number takes up
+ * |key_num_bits|/8 bytes.
+ *
+ * All fields in this struct are stored in network byte order when
+ * serialized. To generate a copy with fields swapped to native byte
+ * order, use the function avb_rsa_public_key_header_validate_and_byteswap().
+ *
+ * The avb_rsa_verify() function expects a key in this serialized
+ * format.
+ *
+ * The 'avbtool extract_public_key' command can be used to generate a
+ * serialized RSA public key.
+ */
+typedef struct AvbRSAPublicKeyHeader {
+ uint32_t key_num_bits;
+ uint32_t n0inv;
+} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_rsa_public_key_header_validate_and_byteswap(
+ const AvbRSAPublicKeyHeader* src,
+ AvbRSAPublicKeyHeader* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_CRYPTO_H_ */
diff --git a/lib/libavb/avb_descriptor.c b/lib/libavb/avb_descriptor.c
new file mode 100644
index 00000000..9f03b977
--- /dev/null
+++ b/lib/libavb/avb_descriptor.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_descriptor.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src,
+ AvbDescriptor* dest) {
+ dest->tag = avb_be64toh(src->tag);
+ dest->num_bytes_following = avb_be64toh(src->num_bytes_following);
+
+ if ((dest->num_bytes_following & 0x07) != 0) {
+ avb_error("Descriptor size is not divisible by 8.\n");
+ return false;
+ }
+ return true;
+}
+
+bool avb_descriptor_foreach(const uint8_t* image_data,
+ size_t image_size,
+ AvbDescriptorForeachFunc foreach_func,
+ void* user_data) {
+ const AvbVBMetaImageHeader* header = NULL;
+ bool ret = false;
+ const uint8_t* image_end;
+ const uint8_t* desc_start;
+ const uint8_t* desc_end;
+ const uint8_t* p;
+
+ if (image_data == NULL) {
+ avb_error("image_data is NULL\n.");
+ goto out;
+ }
+
+ if (foreach_func == NULL) {
+ avb_error("foreach_func is NULL\n.");
+ goto out;
+ }
+
+ if (image_size < sizeof(AvbVBMetaImageHeader)) {
+ avb_error("Length is smaller than header.\n");
+ goto out;
+ }
+
+ /* Ensure magic is correct. */
+ if (avb_memcmp(image_data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_error("Magic is incorrect.\n");
+ goto out;
+ }
+
+ /* Careful, not byteswapped - also ensure it's aligned properly. */
+ avb_assert_aligned(image_data);
+ header = (const AvbVBMetaImageHeader*)image_data;
+ image_end = image_data + image_size;
+
+ desc_start = image_data + sizeof(AvbVBMetaImageHeader) +
+ avb_be64toh(header->authentication_data_block_size) +
+ avb_be64toh(header->descriptors_offset);
+
+ desc_end = desc_start + avb_be64toh(header->descriptors_size);
+
+ if (desc_start < image_data || desc_start > image_end ||
+ desc_end < image_data || desc_end > image_end || desc_end < desc_start) {
+ avb_error("Descriptors not inside passed-in data.\n");
+ goto out;
+ }
+
+ for (p = desc_start; p < desc_end;) {
+ const AvbDescriptor* dh = (const AvbDescriptor*)p;
+ avb_assert_aligned(dh);
+ uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
+ uint64_t nb_total = 0;
+ if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) {
+ avb_error("Invalid descriptor length.\n");
+ goto out;
+ }
+
+ if ((nb_total & 7) != 0) {
+ avb_error("Invalid descriptor length.\n");
+ goto out;
+ }
+
+ if (nb_total + p < desc_start || nb_total + p > desc_end) {
+ avb_error("Invalid data in descriptors array.\n");
+ goto out;
+ }
+
+ if (foreach_func(dh, user_data) == 0) {
+ goto out;
+ }
+
+ if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) {
+ avb_error("Invalid descriptor length.\n");
+ goto out;
+ }
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+static bool count_descriptors(const AvbDescriptor* descriptor,
+ void* user_data) {
+ size_t* num_descriptors = user_data;
+ *num_descriptors += 1;
+ return true;
+}
+
+typedef struct {
+ size_t descriptor_number;
+ const AvbDescriptor** descriptors;
+} SetDescriptorData;
+
+static bool set_descriptors(const AvbDescriptor* descriptor, void* user_data) {
+ SetDescriptorData* data = user_data;
+ data->descriptors[data->descriptor_number++] = descriptor;
+ return true;
+}
+
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+ size_t image_size,
+ size_t* out_num_descriptors) {
+ size_t num_descriptors = 0;
+ SetDescriptorData data;
+
+ avb_descriptor_foreach(
+ image_data, image_size, count_descriptors, &num_descriptors);
+
+ data.descriptor_number = 0;
+ data.descriptors =
+ avb_calloc(sizeof(const AvbDescriptor*) * (num_descriptors + 1));
+ if (data.descriptors == NULL) {
+ return NULL;
+ }
+ avb_descriptor_foreach(image_data, image_size, set_descriptors, &data);
+ avb_assert(data.descriptor_number == num_descriptors);
+
+ if (out_num_descriptors != NULL) {
+ *out_num_descriptors = num_descriptors;
+ }
+
+ return data.descriptors;
+}
diff --git a/lib/libavb/avb_descriptor.h b/lib/libavb/avb_descriptor.h
new file mode 100644
index 00000000..d4f42ac9
--- /dev/null
+++ b/lib/libavb/avb_descriptor.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_DESCRIPTOR_H_
+#define AVB_DESCRIPTOR_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Well-known descriptor tags.
+ *
+ * AVB_DESCRIPTOR_TAG_PROPERTY: see |AvbPropertyDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASHTREE: see |AvbHashtreeDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_HASH: see |AvbHashDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: see |AvbKernelCmdlineDescriptor| struct.
+ * AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: see |AvbChainPartitionDescriptor| struct.
+ */
+typedef enum {
+ AVB_DESCRIPTOR_TAG_PROPERTY,
+ AVB_DESCRIPTOR_TAG_HASHTREE,
+ AVB_DESCRIPTOR_TAG_HASH,
+ AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
+ AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
+} AvbDescriptorTag;
+
+/* The header for a serialized descriptor.
+ *
+ * A descriptor always have two fields, a |tag| (denoting its type,
+ * see the |AvbDescriptorTag| enumeration) and the size of the bytes
+ * following, |num_bytes_following|.
+ *
+ * For padding, |num_bytes_following| is always a multiple of 8.
+ */
+typedef struct AvbDescriptor {
+ uint64_t tag;
+ uint64_t num_bytes_following;
+} AVB_ATTR_PACKED AvbDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_descriptor_validate_and_byteswap(
+ const AvbDescriptor* src, AvbDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Signature for callback function used in avb_descriptor_foreach().
+ * The passed in descriptor is given by |descriptor| and the
+ * |user_data| passed to avb_descriptor_foreach() function is in
+ * |user_data|. Return true to continue iterating, false to stop
+ * iterating.
+ *
+ * Note that |descriptor| points into the image passed to
+ * avb_descriptor_foreach() - all fields need to be byteswapped!
+ */
+typedef bool AvbDescriptorForeachFunc(const AvbDescriptor* descriptor,
+ void* user_data);
+
+/* Convenience function to iterate over all descriptors in an vbmeta
+ * image.
+ *
+ * The function given by |foreach_func| will be called for each
+ * descriptor. The given function should return true to continue
+ * iterating, false to stop.
+ *
+ * The |user_data| parameter will be passed to |foreach_func|.
+ *
+ * Returns false if the iteration was short-circuited, that is if
+ * an invocation of |foreach_func| returned false.
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+bool avb_descriptor_foreach(const uint8_t* image_data,
+ size_t image_size,
+ AvbDescriptorForeachFunc foreach_func,
+ void* user_data);
+
+/* Gets all descriptors in a vbmeta image.
+ *
+ * The return value is a NULL-pointer terminated array of
+ * AvbDescriptor pointers. Free with avb_free() when you are done with
+ * it. If |out_num_descriptors| is non-NULL, the number of descriptors
+ * will be returned there.
+ *
+ * Note that each AvbDescriptor pointer in the array points into
+ * |image_data| - all fields need to be byteswapped!
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a known
+ * good public key. Additionally, |image_data| must be word-aligned.
+ */
+const AvbDescriptor** avb_descriptor_get_all(const uint8_t* image_data,
+ size_t image_size,
+ size_t* out_num_descriptors)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_footer.c b/lib/libavb/avb_footer.c
new file mode 100644
index 00000000..697a7152
--- /dev/null
+++ b/lib/libavb/avb_footer.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_footer.h"
+#include "avb_util.h"
+
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest) {
+ avb_memcpy(dest, src, sizeof(AvbFooter));
+
+ dest->version_major = avb_be32toh(dest->version_major);
+ dest->version_minor = avb_be32toh(dest->version_minor);
+
+ dest->original_image_size = avb_be64toh(dest->original_image_size);
+ dest->vbmeta_offset = avb_be64toh(dest->vbmeta_offset);
+ dest->vbmeta_size = avb_be64toh(dest->vbmeta_size);
+
+ /* Check that magic is correct. */
+ if (avb_safe_memcmp(dest->magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) !=
+ 0) {
+ avb_error("Footer magic is incorrect.\n");
+ return false;
+ }
+
+ /* Ensure we don't attempt to access any fields if the footer major
+ * version is not supported.
+ */
+ if (dest->version_major > AVB_FOOTER_VERSION_MAJOR) {
+ avb_error("No support for footer version.\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/lib/libavb/avb_footer.h b/lib/libavb/avb_footer.h
new file mode 100644
index 00000000..62a6e658
--- /dev/null
+++ b/lib/libavb/avb_footer.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_FOOTER_H_
+#define AVB_FOOTER_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Magic for the footer. */
+#define AVB_FOOTER_MAGIC "AVBf"
+#define AVB_FOOTER_MAGIC_LEN 4
+
+/* Size of the footer. */
+#define AVB_FOOTER_SIZE 64
+
+/* The current footer version used - keep in sync with avbtool. */
+#define AVB_FOOTER_VERSION_MAJOR 1
+#define AVB_FOOTER_VERSION_MINOR 0
+
+/* The struct used as a footer used on partitions, used to find the
+ * AvbVBMetaImageHeader struct. This struct is always stored at the
+ * end of a partition.
+ */
+typedef struct AvbFooter {
+ /* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
+ uint8_t magic[AVB_FOOTER_MAGIC_LEN];
+ /* 4: The major version of the footer struct. */
+ uint32_t version_major;
+ /* 8: The minor version of the footer struct. */
+ uint32_t version_minor;
+
+ /* 12: The original size of the image on the partition. */
+ uint64_t original_image_size;
+
+ /* 20: The offset of the |AvbVBMetaImageHeader| struct. */
+ uint64_t vbmeta_offset;
+
+ /* 28: The size of the vbmeta block (header + auth + aux blocks). */
+ uint64_t vbmeta_size;
+
+ /* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
+ * must be set to zeroes.
+ */
+ uint8_t reserved[28];
+} AVB_ATTR_PACKED AvbFooter;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ */
+bool avb_footer_validate_and_byteswap(const AvbFooter* src, AvbFooter* dest)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_FOOTER_H_ */
diff --git a/lib/libavb/avb_hash_descriptor.c b/lib/libavb/avb_hash_descriptor.c
new file mode 100644
index 00000000..cd1438e0
--- /dev/null
+++ b/lib/libavb/avb_hash_descriptor.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_hash_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+ AvbHashDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbHashDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASH) {
+ avb_error("Invalid tag for hash descriptor.\n");
+ return false;
+ }
+
+ dest->image_size = avb_be64toh(dest->image_size);
+ dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+ dest->salt_len = avb_be32toh(dest->salt_len);
+ dest->digest_len = avb_be32toh(dest->digest_len);
+ dest->flags = avb_be32toh(dest->flags);
+
+ /* Check that partition_name, salt, and digest are fully contained. */
+ expected_size = sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->salt_len) ||
+ !avb_safe_add_to(&expected_size, dest->digest_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/lib/libavb/avb_hash_descriptor.h b/lib/libavb/avb_hash_descriptor.h
new file mode 100644
index 00000000..bede97f8
--- /dev/null
+++ b/lib/libavb/avb_hash_descriptor.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASH_DESCRIPTOR_H_
+#define AVB_HASH_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for hash descriptors.
+ *
+ * AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
+ * partition logic to this partition. This is intentionally a negative boolean
+ * because A/B should be both the default and most used in practice.
+ */
+typedef enum {
+ AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
+} AvbHashDescriptorFlags;
+
+/* A descriptor containing information about hash for an image.
+ *
+ * This descriptor is typically used for boot partitions to verify the
+ * entire kernel+initramfs image before executing it.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |digest_len| bytes of the digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ *
+ * Changes in v1.1:
+ * - flags field is added which supports AVB_HASH_DESCRIPTOR_FLAGS_USE_AB
+ * - digest_len may be zero, which indicates the use of a persistent digest
+ */
+typedef struct AvbHashDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint64_t image_size;
+ uint8_t hash_algorithm[32];
+ uint32_t partition_name_len;
+ uint32_t salt_len;
+ uint32_t digest_len;
+ uint32_t flags;
+ uint8_t reserved[60];
+} AVB_ATTR_PACKED AvbHashDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hash_descriptor_validate_and_byteswap(const AvbHashDescriptor* src,
+ AvbHashDescriptor* dest)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASH_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_hashtree_descriptor.c b/lib/libavb/avb_hashtree_descriptor.c
new file mode 100644
index 00000000..2a61b35a
--- /dev/null
+++ b/lib/libavb/avb_hashtree_descriptor.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_hashtree_descriptor.h"
+#include "avb_util.h"
+
+bool avb_hashtree_descriptor_validate_and_byteswap(
+ const AvbHashtreeDescriptor* src, AvbHashtreeDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbHashtreeDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_HASHTREE) {
+ avb_error("Invalid tag for hashtree descriptor.\n");
+ return false;
+ }
+
+ dest->dm_verity_version = avb_be32toh(dest->dm_verity_version);
+ dest->image_size = avb_be64toh(dest->image_size);
+ dest->tree_offset = avb_be64toh(dest->tree_offset);
+ dest->tree_size = avb_be64toh(dest->tree_size);
+ dest->data_block_size = avb_be32toh(dest->data_block_size);
+ dest->hash_block_size = avb_be32toh(dest->hash_block_size);
+ dest->fec_num_roots = avb_be32toh(dest->fec_num_roots);
+ dest->fec_offset = avb_be64toh(dest->fec_offset);
+ dest->fec_size = avb_be64toh(dest->fec_size);
+ dest->partition_name_len = avb_be32toh(dest->partition_name_len);
+ dest->salt_len = avb_be32toh(dest->salt_len);
+ dest->root_digest_len = avb_be32toh(dest->root_digest_len);
+ dest->flags = avb_be32toh(dest->flags);
+
+ /* Check that partition_name, salt, and root_digest are fully contained. */
+ expected_size = sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->partition_name_len) ||
+ !avb_safe_add_to(&expected_size, dest->salt_len) ||
+ !avb_safe_add_to(&expected_size, dest->root_digest_len)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+ return true;
+}
diff --git a/lib/libavb/avb_hashtree_descriptor.h b/lib/libavb/avb_hashtree_descriptor.h
new file mode 100644
index 00000000..d7f3eb50
--- /dev/null
+++ b/lib/libavb/avb_hashtree_descriptor.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_HASHTREE_DESCRIPTOR_H_
+#define AVB_HASHTREE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for hashtree descriptors.
+ *
+ * AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
+ * partition logic to this partition. This is intentionally a negative boolean
+ * because A/B should be both the default and most used in practice.
+ */
+typedef enum {
+ AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
+} AvbHashtreeDescriptorFlags;
+
+/* A descriptor containing information about a dm-verity hashtree.
+ *
+ * Hash-trees are used to verify large partitions typically containing
+ * file systems. See
+ * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
+ * information about dm-verity.
+ *
+ * Following this struct are |partition_name_len| bytes of the
+ * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
+ * |root_digest_len| bytes of the root digest.
+ *
+ * The |reserved| field is for future expansion and must be set to NUL
+ * bytes.
+ *
+ * Changes in v1.1:
+ * - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
+ * - digest_len may be zero, which indicates the use of a persistent digest
+ */
+typedef struct AvbHashtreeDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint32_t dm_verity_version;
+ uint64_t image_size;
+ uint64_t tree_offset;
+ uint64_t tree_size;
+ uint32_t data_block_size;
+ uint32_t hash_block_size;
+ uint32_t fec_num_roots;
+ uint64_t fec_offset;
+ uint64_t fec_size;
+ uint8_t hash_algorithm[32];
+ uint32_t partition_name_len;
+ uint32_t salt_len;
+ uint32_t root_digest_len;
+ uint32_t flags;
+ uint8_t reserved[60];
+} AVB_ATTR_PACKED AvbHashtreeDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_hashtree_descriptor_validate_and_byteswap(
+ const AvbHashtreeDescriptor* src,
+ AvbHashtreeDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_HASHTREE_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_kernel_cmdline_descriptor.c b/lib/libavb/avb_kernel_cmdline_descriptor.c
new file mode 100644
index 00000000..fa3fe453
--- /dev/null
+++ b/lib/libavb/avb_kernel_cmdline_descriptor.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_util.h"
+
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+ const AvbKernelCmdlineDescriptor* src, AvbKernelCmdlineDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbKernelCmdlineDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) {
+ avb_error("Invalid tag for kernel cmdline descriptor.\n");
+ return false;
+ }
+
+ dest->flags = avb_be32toh(dest->flags);
+ dest->kernel_cmdline_length = avb_be32toh(dest->kernel_cmdline_length);
+
+ /* Check that kernel_cmdline is fully contained. */
+ expected_size = sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor);
+ if (!avb_safe_add_to(&expected_size, dest->kernel_cmdline_length)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/lib/libavb/avb_kernel_cmdline_descriptor.h b/lib/libavb/avb_kernel_cmdline_descriptor.h
new file mode 100644
index 00000000..246fbdac
--- /dev/null
+++ b/lib/libavb/avb_kernel_cmdline_descriptor.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+#define AVB_KERNEL_CMDLINE_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Flags for kernel command-line descriptors.
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED: The
+ * cmdline will only be applied if hashtree verification is not
+ * disabled (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ *
+ * AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED: The cmdline
+ * will only be applied if hashtree verification is disabled
+ * (cf. AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED).
+ */
+typedef enum {
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
+} AvbKernelCmdlineFlags;
+
+/* A descriptor containing information to be appended to the kernel
+ * command-line.
+ *
+ * The |flags| field contains flags from the AvbKernelCmdlineFlags
+ * enumeration.
+ *
+ * Following this struct are |kernel_cmdline_len| bytes with the
+ * kernel command-line (UTF-8 encoded).
+ */
+typedef struct AvbKernelCmdlineDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint32_t flags;
+ uint32_t kernel_cmdline_length;
+} AVB_ATTR_PACKED AvbKernelCmdlineDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_kernel_cmdline_descriptor_validate_and_byteswap(
+ const AvbKernelCmdlineDescriptor* src,
+ AvbKernelCmdlineDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_KERNEL_CMDLINE_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_ops.h b/lib/libavb/avb_ops.h
new file mode 100644
index 00000000..6a5c589d
--- /dev/null
+++ b/lib/libavb/avb_ops.h
@@ -0,0 +1,321 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_OPS_H_
+#define AVB_OPS_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Well-known names of named persistent values. */
+#define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest."
+#define AVB_NPV_MANAGED_VERITY_MODE "avb.managed_verity_mode"
+
+/* Return codes used for I/O operations.
+ *
+ * AVB_IO_RESULT_OK is returned if the requested operation was
+ * successful.
+ *
+ * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
+ * or other subsystem) encountered an I/O error.
+ *
+ * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
+ *
+ * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
+ * partition does not exist.
+ *
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
+ * range of bytes requested to be read or written is outside the range
+ * of the partition.
+ *
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value
+ * does not exist.
+ *
+ * AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent
+ * value size is not supported or does not match the expected size.
+ *
+ * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small
+ * for the requested operation.
+ */
+typedef enum {
+ AVB_IO_RESULT_OK,
+ AVB_IO_RESULT_ERROR_OOM,
+ AVB_IO_RESULT_ERROR_IO,
+ AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
+ AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
+ AVB_IO_RESULT_ERROR_NO_SUCH_VALUE,
+ AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE,
+ AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE,
+} AvbIOResult;
+
+struct AvbOps;
+typedef struct AvbOps AvbOps;
+
+/* Forward-declaration of operations in libavb_ab. */
+struct AvbABOps;
+
+/* Forward-declaration of operations in libavb_atx. */
+struct AvbAtxOps;
+
+/* High-level operations/functions/methods that are platform
+ * dependent.
+ *
+ * Operations may be added in the future so when implementing it
+ * always make sure to zero out sizeof(AvbOps) bytes of the struct to
+ * ensure that unimplemented operations are set to NULL.
+ */
+struct AvbOps {
+ /* This pointer can be used by the application/bootloader using
+ * libavb and is typically used in each operation to get a pointer
+ * to platform-specific resources. It cannot be used by libraries.
+ */
+ void* user_data;
+
+ /* If libavb_ab is used, this should point to the
+ * AvbABOps. Otherwise it must be set to NULL.
+ */
+ struct AvbABOps* ab_ops;
+
+ /* If libavb_atx is used, this should point to the
+ * AvbAtxOps. Otherwise it must be set to NULL.
+ */
+ struct AvbAtxOps* atx_ops;
+
+ /* Reads |num_bytes| from offset |offset| from partition with name
+ * |partition| (NUL-terminated UTF-8 string). If |offset| is
+ * negative, its absolute value should be interpreted as the number
+ * of bytes from the end of the partition.
+ *
+ * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+ * there is no partition with the given name,
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+ * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if
+ * there was an I/O error from the underlying I/O subsystem. If the
+ * operation succeeds as requested AVB_IO_RESULT_OK is returned and
+ * the data is available in |buffer|.
+ *
+ * The only time partial I/O may occur is if reading beyond the end
+ * of the partition. In this case the value returned in
+ * |out_num_read| may be smaller than |num_bytes|.
+ */
+ AvbIOResult (*read_from_partition)(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ void* buffer,
+ size_t* out_num_read);
+
+ /* Gets the starting pointer of a partition that is pre-loaded in memory, and
+ * save it to |out_pointer|. The preloaded partition is expected to be
+ * |num_bytes|, where the actual preloaded byte count is returned in
+ * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than
+ * |num_bytes|.
+ *
+ * This provides an alternative way to access a partition that is preloaded
+ * into memory without a full memory copy. When this function pointer is not
+ * set (has value NULL), or when the |out_pointer| is set to NULL as a result,
+ * |read_from_partition| will be used as the fallback. This function is mainly
+ * used for accessing the entire partition content to calculate its hash.
+ *
+ * Preloaded partition data must outlive the lifespan of the
+ * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs.
+ */
+ AvbIOResult (*get_preloaded_partition)(AvbOps* ops,
+ const char* partition,
+ size_t num_bytes,
+ uint8_t** out_pointer,
+ size_t* out_num_bytes_preloaded);
+
+ /* Writes |num_bytes| from |bffer| at offset |offset| to partition
+ * with name |partition| (NUL-terminated UTF-8 string). If |offset|
+ * is negative, its absolute value should be interpreted as the
+ * number of bytes from the end of the partition.
+ *
+ * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if
+ * there is no partition with the given name,
+ * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested
+ * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO
+ * if there was an I/O error from the underlying I/O subsystem. If
+ * the operation succeeds as requested AVB_IO_RESULT_OK is
+ * returned.
+ *
+ * This function never does any partial I/O, it either transfers all
+ * of the requested bytes or returns an error.
+ */
+ AvbIOResult (*write_to_partition)(AvbOps* ops,
+ const char* partition,
+ int64_t offset,
+ size_t num_bytes,
+ const void* buffer);
+
+ /* Checks if the given public key used to sign the 'vbmeta'
+ * partition is trusted. Boot loaders typically compare this with
+ * embedded key material generated with 'avbtool
+ * extract_public_key'.
+ *
+ * The public key is in the array pointed to by |public_key_data|
+ * and is of |public_key_length| bytes.
+ *
+ * If there is no public key metadata (set with the avbtool option
+ * --public_key_metadata) then |public_key_metadata| will be set to
+ * NULL. Otherwise this field points to the data which is
+ * |public_key_metadata_length| bytes long.
+ *
+ * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
+ * true if trusted or false if untrusted.
+ *
+ * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
+ * avb_slot_verify() then this operation is never used. Instead, the
+ * validate_public_key_for_partition() operation is used
+ */
+ AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted);
+
+ /* Gets the rollback index corresponding to the location given by
+ * |rollback_index_location|. The value is returned in
+ * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
+ * index was retrieved, otherwise an error code.
+ *
+ * A device may have a limited amount of rollback index locations (say,
+ * one or four) so may error out if |rollback_index_location| exceeds
+ * this number.
+ */
+ AvbIOResult (*read_rollback_index)(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t* out_rollback_index);
+
+ /* Sets the rollback index corresponding to the location given by
+ * |rollback_index_location| to |rollback_index|. Returns
+ * AVB_IO_RESULT_OK if the rollback index was set, otherwise an
+ * error code.
+ *
+ * A device may have a limited amount of rollback index locations (say,
+ * one or four) so may error out if |rollback_index_location| exceeds
+ * this number.
+ */
+ AvbIOResult (*write_rollback_index)(AvbOps* ops,
+ size_t rollback_index_location,
+ uint64_t rollback_index);
+
+ /* Gets whether the device is unlocked. The value is returned in
+ * |out_is_unlocked| (true if unlocked, false otherwise). Returns
+ * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
+ * code.
+ */
+ AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
+
+ /* Gets the unique partition GUID for a partition with name in
+ * |partition| (NUL-terminated UTF-8 string). The GUID is copied as
+ * a string into |guid_buf| of size |guid_buf_size| and will be NUL
+ * terminated. The string must be lower-case and properly
+ * hyphenated. For example:
+ *
+ * 527c1c6d-6361-4593-8842-3c78fcd39219
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size);
+
+ /* Gets the size of a partition with the name in |partition|
+ * (NUL-terminated UTF-8 string). Returns the value in
+ * |out_size_num_bytes|.
+ *
+ * If the partition doesn't exist the AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION
+ * error code should be returned.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*get_size_of_partition)(AvbOps* ops,
+ const char* partition,
+ uint64_t* out_size_num_bytes);
+
+ /* Reads a persistent value corresponding to the given |name|. The value is
+ * returned in |out_buffer| which must point to |buffer_size| bytes. On
+ * success |out_num_bytes_read| contains the number of bytes read into
+ * |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned,
+ * |out_num_bytes_read| contains the number of bytes that would have been read
+ * which can be used to allocate a buffer.
+ *
+ * The |buffer_size| may be zero and the |out_buffer| may be NULL, but if
+ * |out_buffer| is NULL then |buffer_size| *must* be zero.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ *
+ * If the value does not exist, is not supported, or is not populated, returns
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the
+ * size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE.
+ *
+ * This operation is currently only used to support persistent digests or the
+ * AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a
+ * device does not use one of these features this function pointer can be set
+ * to NULL.
+ */
+ AvbIOResult (*read_persistent_value)(AvbOps* ops,
+ const char* name,
+ size_t buffer_size,
+ uint8_t* out_buffer,
+ size_t* out_num_bytes_read);
+
+ /* Writes a persistent value corresponding to the given |name|. The value is
+ * supplied in |value| which must point to |value_size| bytes. Any existing
+ * value with the same name is overwritten. If |value_size| is zero, future
+ * calls to |read_persistent_value| will return
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ *
+ * If the value |name| is not supported, returns
+ * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported,
+ * returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE.
+ *
+ * This operation is currently only used to support persistent digests or the
+ * AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a
+ * device does not use one of these features this function pointer can be set
+ * to NULL.
+ */
+ AvbIOResult (*write_persistent_value)(AvbOps* ops,
+ const char* name,
+ size_t value_size,
+ const uint8_t* value);
+
+ /* Like validate_vbmeta_public_key() but for when the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
+ * partition to get the public key for is passed in |partition_name|.
+ *
+ * Also returns the rollback index location to use for the partition, in
+ * |out_rollback_index_location|.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*validate_public_key_for_partition)(
+ AvbOps* ops,
+ const char* partition,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted,
+ uint32_t* out_rollback_index_location);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_OPS_H_ */
diff --git a/lib/libavb/avb_property_descriptor.c b/lib/libavb/avb_property_descriptor.c
new file mode 100644
index 00000000..589c9631
--- /dev/null
+++ b/lib/libavb/avb_property_descriptor.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_property_descriptor.h"
+#include "avb_util.h"
+
+bool avb_property_descriptor_validate_and_byteswap(
+ const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
+ uint64_t expected_size;
+
+ avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));
+
+ if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
+ (AvbDescriptor*)dest))
+ return false;
+
+ if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+ avb_error("Invalid tag for property descriptor.\n");
+ return false;
+ }
+
+ dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
+ dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);
+
+ /* Check that key and value are fully contained. */
+ expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
+ if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
+ !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
+ avb_error("Overflow while adding up sizes.\n");
+ return false;
+ }
+ if (expected_size > dest->parent_descriptor.num_bytes_following) {
+ avb_error("Descriptor payload size overflow.\n");
+ return false;
+ }
+
+ return true;
+}
+
+typedef struct {
+ const char* key;
+ size_t key_size;
+ const char* ret_value;
+ size_t ret_value_size;
+} PropertyIteratorData;
+
+static bool property_lookup_desc_foreach(const AvbDescriptor* header,
+ void* user_data) {
+ PropertyIteratorData* data = (PropertyIteratorData*)user_data;
+ AvbPropertyDescriptor prop_desc;
+ const uint8_t* p;
+ bool ret = true;
+
+ if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
+ goto out;
+ }
+
+ if (!avb_property_descriptor_validate_and_byteswap(
+ (const AvbPropertyDescriptor*)header, &prop_desc)) {
+ goto out;
+ }
+
+ p = (const uint8_t*)header;
+ if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
+ avb_error("No terminating NUL byte in key.\n");
+ goto out;
+ }
+
+ if (data->key_size == prop_desc.key_num_bytes) {
+ if (avb_memcmp(p + sizeof(AvbPropertyDescriptor),
+ data->key,
+ data->key_size) == 0) {
+ data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
+ prop_desc.key_num_bytes + 1);
+ data->ret_value_size = prop_desc.value_num_bytes;
+ /* Stop iterating. */
+ ret = false;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+const char* avb_property_lookup(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ size_t* out_value_size) {
+ PropertyIteratorData data;
+
+ if (key_size == 0) {
+ key_size = avb_strlen(key);
+ }
+
+ data.key = key;
+ data.key_size = key_size;
+
+ if (avb_descriptor_foreach(
+ image_data, image_size, property_lookup_desc_foreach, &data) == 0) {
+ if (out_value_size != NULL) {
+ *out_value_size = data.ret_value_size;
+ }
+ return data.ret_value;
+ }
+
+ if (out_value_size != NULL) {
+ *out_value_size = 0;
+ }
+ return NULL;
+}
+
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ uint64_t* out_value) {
+ const char* value;
+ bool ret = false;
+ uint64_t parsed_val;
+ int base;
+ int n;
+
+ value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
+ if (value == NULL) {
+ goto out;
+ }
+
+ base = 10;
+ if (avb_memcmp(value, "0x", 2) == 0) {
+ base = 16;
+ value += 2;
+ }
+
+ parsed_val = 0;
+ for (n = 0; value[n] != '\0'; n++) {
+ int c = value[n];
+ int digit;
+
+ parsed_val *= base;
+
+ if (c >= '0' && c <= '9') {
+ digit = c - '0';
+ } else if (base == 16 && c >= 'a' && c <= 'f') {
+ digit = c - 'a' + 10;
+ } else if (base == 16 && c >= 'A' && c <= 'F') {
+ digit = c - 'A' + 10;
+ } else {
+ avb_error("Invalid digit.\n");
+ goto out;
+ }
+
+ parsed_val += digit;
+ }
+
+ ret = true;
+ if (out_value != NULL) {
+ *out_value = parsed_val;
+ }
+
+out:
+ return ret;
+}
diff --git a/lib/libavb/avb_property_descriptor.h b/lib/libavb/avb_property_descriptor.h
new file mode 100644
index 00000000..917c58f9
--- /dev/null
+++ b/lib/libavb/avb_property_descriptor.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_PROPERTY_DESCRIPTOR_H_
+#define AVB_PROPERTY_DESCRIPTOR_H_
+
+#include "avb_descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A descriptor for properties (free-form key/value pairs).
+ *
+ * Following this struct are |key_num_bytes| bytes of key data,
+ * followed by a NUL byte, then |value_num_bytes| bytes of value data,
+ * followed by a NUL byte and then enough padding to make the combined
+ * size a multiple of 8.
+ */
+typedef struct AvbPropertyDescriptor {
+ AvbDescriptor parent_descriptor;
+ uint64_t key_num_bytes;
+ uint64_t value_num_bytes;
+} AVB_ATTR_PACKED AvbPropertyDescriptor;
+
+/* Copies |src| to |dest| and validates, byte-swapping fields in the
+ * process if needed. Returns true if valid, false if invalid.
+ *
+ * Data following the struct is not validated nor copied.
+ */
+bool avb_property_descriptor_validate_and_byteswap(
+ const AvbPropertyDescriptor* src,
+ AvbPropertyDescriptor* dest) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Convenience function for looking up the value for a property with
+ * name |key| in a vbmeta image. If |key_size| is 0, |key| must be
+ * NUL-terminated.
+ *
+ * The |image_data| parameter must be a pointer to a vbmeta image of
+ * size |image_size|.
+ *
+ * This function returns a pointer to the value inside the passed-in
+ * image or NULL if not found. Note that the value is always
+ * guaranteed to be followed by a NUL byte.
+ *
+ * If the value was found and |out_value_size| is not NULL, the size
+ * of the value is returned there.
+ *
+ * This function is O(n) in number of descriptors so if you need to
+ * look up a lot of values, you may want to build a more efficient
+ * lookup-table by manually walking all descriptors using
+ * avb_descriptor_foreach().
+ *
+ * Before using this function, you MUST verify |image_data| with
+ * avb_vbmeta_image_verify() and reject it unless it's signed by a
+ * known good public key.
+ */
+const char* avb_property_lookup(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ size_t* out_value_size)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_property_lookup() but parses the intial portions of the
+ * value as an unsigned 64-bit integer. Both decimal and hexadecimal
+ * representations (e.g. "0x2a") are supported. Returns false on
+ * failure and true on success. On success, the parsed value is
+ * returned in |out_value|.
+ */
+bool avb_property_lookup_uint64(const uint8_t* image_data,
+ size_t image_size,
+ const char* key,
+ size_t key_size,
+ uint64_t* out_value)
+ AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_PROPERTY_DESCRIPTOR_H_ */
diff --git a/lib/libavb/avb_rsa.c b/lib/libavb/avb_rsa.c
new file mode 100644
index 00000000..bbf15626
--- /dev/null
+++ b/lib/libavb/avb_rsa.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: MIT OR BSD-3-Clause
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+/* Implementation of RSA signature verification which uses a pre-processed
+ * key for computation. The code extends libmincrypt RSA verification code to
+ * support multiple RSA key lengths and hash digest algorithms.
+ */
+
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+
+typedef struct IAvbKey {
+ unsigned int len; /* Length of n[] in number of uint32_t */
+ uint32_t n0inv; /* -1 / n[0] mod 2^32 */
+ uint32_t* n; /* modulus as array (host-byte order) */
+ uint32_t* rr; /* R^2 as array (host-byte order) */
+} IAvbKey;
+
+static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
+ AvbRSAPublicKeyHeader h;
+ IAvbKey* key = NULL;
+ size_t expected_length;
+ unsigned int i;
+ const uint8_t* n;
+ const uint8_t* rr;
+
+ if (!avb_rsa_public_key_header_validate_and_byteswap(
+ (const AvbRSAPublicKeyHeader*)data, &h)) {
+ avb_error("Invalid key.\n");
+ goto fail;
+ }
+
+ if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
+ h.key_num_bits == 8192)) {
+ avb_error("Unexpected key length.\n");
+ goto fail;
+ }
+
+ expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
+ if (length != expected_length) {
+ avb_error("Key does not match expected length.\n");
+ goto fail;
+ }
+
+ n = data + sizeof(AvbRSAPublicKeyHeader);
+ rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
+
+ /* Store n and rr following the key header so we only have to do one
+ * allocation.
+ */
+ key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
+ if (key == NULL) {
+ goto fail;
+ }
+
+ key->len = h.key_num_bits / 32;
+ key->n0inv = h.n0inv;
+ key->n = (uint32_t*)(key + 1); /* Skip ahead sizeof(IAvbKey) bytes. */
+ key->rr = key->n + key->len;
+
+ /* Crypto-code below (modpowF4() and friends) expects the key in
+ * little-endian format (rather than the format we're storing the
+ * key in), so convert it.
+ */
+ for (i = 0; i < key->len; i++) {
+ key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
+ key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
+ }
+ return key;
+
+fail:
+ if (key != NULL) {
+ avb_free(key);
+ }
+ return NULL;
+}
+
+static void iavb_free_parsed_key(IAvbKey* key) {
+ avb_free(key);
+}
+
+/* a[] -= mod */
+static void subM(const IAvbKey* key, uint32_t* a) {
+ int64_t A = 0;
+ uint32_t i;
+ for (i = 0; i < key->len; ++i) {
+ A += (uint64_t)a[i] - key->n[i];
+ a[i] = (uint32_t)A;
+ A >>= 32;
+ }
+}
+
+/* return a[] >= mod */
+static int geM(const IAvbKey* key, uint32_t* a) {
+ uint32_t i;
+ for (i = key->len; i;) {
+ --i;
+ if (a[i] < key->n[i]) {
+ return 0;
+ }
+ if (a[i] > key->n[i]) {
+ return 1;
+ }
+ }
+ return 1; /* equal */
+}
+
+/* montgomery c[] += a * b[] / R % mod */
+static void montMulAdd(const IAvbKey* key,
+ uint32_t* c,
+ const uint32_t a,
+ const uint32_t* b) {
+ uint64_t A = (uint64_t)a * b[0] + c[0];
+ uint32_t d0 = (uint32_t)A * key->n0inv;
+ uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+ uint32_t i;
+
+ for (i = 1; i < key->len; ++i) {
+ A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+ B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+ c[i - 1] = (uint32_t)B;
+ }
+
+ A = (A >> 32) + (B >> 32);
+
+ c[i - 1] = (uint32_t)A;
+
+ if (A >> 32) {
+ subM(key, c);
+ }
+}
+
+/* montgomery c[] = a[] * b[] / R % mod */
+static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
+ uint32_t i;
+ for (i = 0; i < key->len; ++i) {
+ c[i] = 0;
+ }
+ for (i = 0; i < key->len; ++i) {
+ montMulAdd(key, c, a[i], b);
+ }
+}
+
+/* In-place public exponentiation. (65537}
+ * Input and output big-endian byte array in inout.
+ */
+static void modpowF4(const IAvbKey* key, uint8_t* inout) {
+ uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
+ if (a == NULL || aR == NULL || aaR == NULL) {
+ goto out;
+ }
+
+ uint32_t* aaa = aaR; /* Re-use location. */
+ int i;
+
+ /* Convert from big endian byte array to little endian word array. */
+ for (i = 0; i < (int)key->len; ++i) {
+ uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+ (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+ (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+ (inout[((key->len - 1 - i) * 4) + 3] << 0);
+ a[i] = tmp;
+ }
+
+ montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
+ for (i = 0; i < 16; i += 2) {
+ montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
+ montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */
+ }
+ montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */
+
+ /* Make sure aaa < mod; aaa is at most 1x mod too large. */
+ if (geM(key, aaa)) {
+ subM(key, aaa);
+ }
+
+ /* Convert to bigendian byte array */
+ for (i = (int)key->len - 1; i >= 0; --i) {
+ uint32_t tmp = aaa[i];
+ *inout++ = (uint8_t)(tmp >> 24);
+ *inout++ = (uint8_t)(tmp >> 16);
+ *inout++ = (uint8_t)(tmp >> 8);
+ *inout++ = (uint8_t)(tmp >> 0);
+ }
+
+out:
+ if (a != NULL) {
+ avb_free(a);
+ }
+ if (aR != NULL) {
+ avb_free(aR);
+ }
+ if (aaR != NULL) {
+ avb_free(aaR);
+ }
+}
+
+/* Verify a RSA PKCS1.5 signature against an expected hash.
+ * Returns false on failure, true on success.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+ size_t key_num_bytes,
+ const uint8_t* sig,
+ size_t sig_num_bytes,
+ const uint8_t* hash,
+ size_t hash_num_bytes,
+ const uint8_t* padding,
+ size_t padding_num_bytes) {
+ uint8_t* buf = NULL;
+ IAvbKey* parsed_key = NULL;
+ bool success = false;
+
+ if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
+ avb_error("Invalid input.\n");
+ goto out;
+ }
+
+ parsed_key = iavb_parse_key_data(key, key_num_bytes);
+ if (parsed_key == NULL) {
+ avb_error("Error parsing key.\n");
+ goto out;
+ }
+
+ if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
+ avb_error("Signature length does not match key length.\n");
+ goto out;
+ }
+
+ if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
+ avb_error("Padding length does not match hash and signature lengths.\n");
+ goto out;
+ }
+
+ buf = (uint8_t*)avb_malloc(sig_num_bytes);
+ if (buf == NULL) {
+ avb_error("Error allocating memory.\n");
+ goto out;
+ }
+ avb_memcpy(buf, sig, sig_num_bytes);
+
+ modpowF4(parsed_key, buf);
+
+ /* Check padding bytes.
+ *
+ * Even though there are probably no timing issues here, we use
+ * avb_safe_memcmp() just to be on the safe side.
+ */
+ if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
+ avb_error("Padding check failed.\n");
+ goto out;
+ }
+
+ /* Check hash. */
+ if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
+ avb_error("Hash check failed.\n");
+ goto out;
+ }
+
+ success = true;
+
+out:
+ if (parsed_key != NULL) {
+ iavb_free_parsed_key(parsed_key);
+ }
+ if (buf != NULL) {
+ avb_free(buf);
+ }
+ return success;
+}
diff --git a/lib/libavb/avb_rsa.h b/lib/libavb/avb_rsa.h
new file mode 100644
index 00000000..8741790e
--- /dev/null
+++ b/lib/libavb/avb_rsa.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: MIT OR BSD-3-Clause */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_rsa.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_RSA_H_
+#define AVB_RSA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Using the key given by |key|, verify a RSA signature |sig| of
+ * length |sig_num_bytes| against an expected |hash| of length
+ * |hash_num_bytes|. The padding to expect must be passed in using
+ * |padding| of length |padding_num_bytes|.
+ *
+ * The data in |key| must match the format defined in
+ * |AvbRSAPublicKeyHeader|, including the two large numbers
+ * following. The |key_num_bytes| must be the size of the entire
+ * serialized key.
+ *
+ * Returns false if verification fails, true otherwise.
+ */
+bool avb_rsa_verify(const uint8_t* key,
+ size_t key_num_bytes,
+ const uint8_t* sig,
+ size_t sig_num_bytes,
+ const uint8_t* hash,
+ size_t hash_num_bytes,
+ const uint8_t* padding,
+ size_t padding_num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_RSA_H_ */
diff --git a/lib/libavb/avb_sha.h b/lib/libavb/avb_sha.h
new file mode 100644
index 00000000..f5d02e09
--- /dev/null
+++ b/lib/libavb/avb_sha.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#ifdef AVB_INSIDE_LIBAVB_H
+#error "You can't include avb_sha.h in the public header libavb.h."
+#endif
+
+#ifndef AVB_COMPILATION
+#error "Never include this file, it may only be used from internal avb code."
+#endif
+
+#ifndef AVB_SHA_H_
+#define AVB_SHA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_sysdeps.h"
+
+/* Block size in bytes of a SHA-256 digest. */
+#define AVB_SHA256_BLOCK_SIZE 64
+
+
+/* Block size in bytes of a SHA-512 digest. */
+#define AVB_SHA512_BLOCK_SIZE 128
+
+/* Data structure used for SHA-256. */
+typedef struct {
+ uint32_t h[8];
+ uint64_t tot_len;
+ size_t len;
+ uint8_t block[2 * AVB_SHA256_BLOCK_SIZE];
+ uint8_t buf[AVB_SHA256_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA256Ctx;
+
+/* Data structure used for SHA-512. */
+typedef struct {
+ uint64_t h[8];
+ uint64_t tot_len;
+ size_t len;
+ uint8_t block[2 * AVB_SHA512_BLOCK_SIZE];
+ uint8_t buf[AVB_SHA512_DIGEST_SIZE]; /* Used for storing the final digest. */
+} AvbSHA512Ctx;
+
+/* Initializes the SHA-256 context. */
+void avb_sha256_init(AvbSHA256Ctx* ctx);
+
+/* Updates the SHA-256 context with |len| bytes from |data|. */
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len);
+
+/* Returns the SHA-256 digest. */
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Initializes the SHA-512 context. */
+void avb_sha512_init(AvbSHA512Ctx* ctx);
+
+/* Updates the SHA-512 context with |len| bytes from |data|. */
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len);
+
+/* Returns the SHA-512 digest. */
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SHA_H_ */
diff --git a/lib/libavb/avb_sha256.c b/lib/libavb/avb_sha256.c
new file mode 100644
index 00000000..86ecca57
--- /dev/null
+++ b/lib/libavb/avb_sha256.c
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str) \
+ { \
+ *((str) + 3) = (uint8_t)((x)); \
+ *((str) + 2) = (uint8_t)((x) >> 8); \
+ *((str) + 1) = (uint8_t)((x) >> 16); \
+ *((str) + 0) = (uint8_t)((x) >> 24); \
+ }
+
+#define UNPACK64(x, str) \
+ { \
+ *((str) + 7) = (uint8_t)x; \
+ *((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
+ *((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
+ *((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
+ *((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
+ *((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
+ *((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
+ *((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
+ }
+
+#define PACK32(str, x) \
+ { \
+ *(x) = ((uint32_t) * ((str) + 3)) | ((uint32_t) * ((str) + 2) << 8) | \
+ ((uint32_t) * ((str) + 1) << 16) | \
+ ((uint32_t) * ((str) + 0) << 24); \
+ }
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+ { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+ { \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + \
+ w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+ }
+
+static const uint32_t sha256_h0[8] = {0x6a09e667,
+ 0xbb67ae85,
+ 0x3c6ef372,
+ 0xa54ff53a,
+ 0x510e527f,
+ 0x9b05688c,
+ 0x1f83d9ab,
+ 0x5be0cd19};
+
+static const uint32_t sha256_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};
+
+/* SHA-256 implementation */
+void avb_sha256_init(AvbSHA256Ctx* ctx) {
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha256_h0[i];
+ }
+#else
+ ctx->h[0] = sha256_h0[0];
+ ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2];
+ ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4];
+ ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6];
+ ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+static void SHA256_transform(AvbSHA256Ctx* ctx,
+ const uint8_t* message,
+ size_t block_nb) {
+ uint32_t w[64];
+ uint32_t wv[8];
+ uint32_t t1, t2;
+ const unsigned char* sub_block;
+ size_t i;
+
+#ifndef UNROLL_LOOPS
+ size_t j;
+#endif
+
+ for (i = 0; i < block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] +
+ w[j];
+ t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK32(&sub_block[0], &w[0]);
+ PACK32(&sub_block[4], &w[1]);
+ PACK32(&sub_block[8], &w[2]);
+ PACK32(&sub_block[12], &w[3]);
+ PACK32(&sub_block[16], &w[4]);
+ PACK32(&sub_block[20], &w[5]);
+ PACK32(&sub_block[24], &w[6]);
+ PACK32(&sub_block[28], &w[7]);
+ PACK32(&sub_block[32], &w[8]);
+ PACK32(&sub_block[36], &w[9]);
+ PACK32(&sub_block[40], &w[10]);
+ PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]);
+ PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]);
+ PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16);
+ SHA256_SCR(17);
+ SHA256_SCR(18);
+ SHA256_SCR(19);
+ SHA256_SCR(20);
+ SHA256_SCR(21);
+ SHA256_SCR(22);
+ SHA256_SCR(23);
+ SHA256_SCR(24);
+ SHA256_SCR(25);
+ SHA256_SCR(26);
+ SHA256_SCR(27);
+ SHA256_SCR(28);
+ SHA256_SCR(29);
+ SHA256_SCR(30);
+ SHA256_SCR(31);
+ SHA256_SCR(32);
+ SHA256_SCR(33);
+ SHA256_SCR(34);
+ SHA256_SCR(35);
+ SHA256_SCR(36);
+ SHA256_SCR(37);
+ SHA256_SCR(38);
+ SHA256_SCR(39);
+ SHA256_SCR(40);
+ SHA256_SCR(41);
+ SHA256_SCR(42);
+ SHA256_SCR(43);
+ SHA256_SCR(44);
+ SHA256_SCR(45);
+ SHA256_SCR(46);
+ SHA256_SCR(47);
+ SHA256_SCR(48);
+ SHA256_SCR(49);
+ SHA256_SCR(50);
+ SHA256_SCR(51);
+ SHA256_SCR(52);
+ SHA256_SCR(53);
+ SHA256_SCR(54);
+ SHA256_SCR(55);
+ SHA256_SCR(56);
+ SHA256_SCR(57);
+ SHA256_SCR(58);
+ SHA256_SCR(59);
+ SHA256_SCR(60);
+ SHA256_SCR(61);
+ SHA256_SCR(62);
+ SHA256_SCR(63);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
+ SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
+ SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
+ SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
+ SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
+ SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
+ SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
+ SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
+ SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void avb_sha256_update(AvbSHA256Ctx* ctx, const uint8_t* data, size_t len) {
+ size_t block_nb;
+ size_t new_len, rem_len, tmp_len;
+ const uint8_t* shifted_data;
+
+ tmp_len = AVB_SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+ if (ctx->len + len < AVB_SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / AVB_SHA256_BLOCK_SIZE;
+
+ shifted_data = data + rem_len;
+
+ SHA256_transform(ctx, ctx->block, 1);
+ SHA256_transform(ctx, shifted_data, block_nb);
+
+ rem_len = new_len % AVB_SHA256_BLOCK_SIZE;
+
+ avb_memcpy(ctx->block, &shifted_data[block_nb << 6], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+uint8_t* avb_sha256_final(AvbSHA256Ctx* ctx) {
+ size_t block_nb;
+ size_t pm_len;
+ uint64_t len_b;
+#ifndef UNROLL_LOOPS
+ size_t i;
+#endif
+
+ block_nb =
+ (1 + ((AVB_SHA256_BLOCK_SIZE - 9) < (ctx->len % AVB_SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK64(len_b, ctx->block + pm_len - 8);
+
+ SHA256_transform(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 8; i++) {
+ UNPACK32(ctx->h[i], &ctx->buf[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &ctx->buf[0]);
+ UNPACK32(ctx->h[1], &ctx->buf[4]);
+ UNPACK32(ctx->h[2], &ctx->buf[8]);
+ UNPACK32(ctx->h[3], &ctx->buf[12]);
+ UNPACK32(ctx->h[4], &ctx->buf[16]);
+ UNPACK32(ctx->h[5], &ctx->buf[20]);
+ UNPACK32(ctx->h[6], &ctx->buf[24]);
+ UNPACK32(ctx->h[7], &ctx->buf[28]);
+#endif /* !UNROLL_LOOPS */
+
+ return ctx->buf;
+}
diff --git a/lib/libavb/avb_sha512.c b/lib/libavb/avb_sha512.c
new file mode 100644
index 00000000..b19054fc
--- /dev/null
+++ b/lib/libavb/avb_sha512.c
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ */
+
+#include "avb_sha.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str) \
+ { \
+ *((str) + 3) = (uint8_t)((x)); \
+ *((str) + 2) = (uint8_t)((x) >> 8); \
+ *((str) + 1) = (uint8_t)((x) >> 16); \
+ *((str) + 0) = (uint8_t)((x) >> 24); \
+ }
+
+#define UNPACK64(x, str) \
+ { \
+ *((str) + 7) = (uint8_t)x; \
+ *((str) + 6) = (uint8_t)((uint64_t)x >> 8); \
+ *((str) + 5) = (uint8_t)((uint64_t)x >> 16); \
+ *((str) + 4) = (uint8_t)((uint64_t)x >> 24); \
+ *((str) + 3) = (uint8_t)((uint64_t)x >> 32); \
+ *((str) + 2) = (uint8_t)((uint64_t)x >> 40); \
+ *((str) + 1) = (uint8_t)((uint64_t)x >> 48); \
+ *((str) + 0) = (uint8_t)((uint64_t)x >> 56); \
+ }
+
+#define PACK64(str, x) \
+ { \
+ *(x) = \
+ ((uint64_t) * ((str) + 7)) | ((uint64_t) * ((str) + 6) << 8) | \
+ ((uint64_t) * ((str) + 5) << 16) | ((uint64_t) * ((str) + 4) << 24) | \
+ ((uint64_t) * ((str) + 3) << 32) | ((uint64_t) * ((str) + 2) << 40) | \
+ ((uint64_t) * ((str) + 1) << 48) | ((uint64_t) * ((str) + 0) << 56); \
+ }
+
+/* Macros used for loops unrolling */
+
+#define SHA512_SCR(i) \
+ { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; }
+
+#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \
+ { \
+ t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + \
+ w[j]; \
+ t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+ }
+
+static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL};
+
+static const uint64_t sha512_k[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* SHA-512 implementation */
+
+void avb_sha512_init(AvbSHA512Ctx* ctx) {
+#ifdef UNROLL_LOOPS_SHA512
+ ctx->h[0] = sha512_h0[0];
+ ctx->h[1] = sha512_h0[1];
+ ctx->h[2] = sha512_h0[2];
+ ctx->h[3] = sha512_h0[3];
+ ctx->h[4] = sha512_h0[4];
+ ctx->h[5] = sha512_h0[5];
+ ctx->h[6] = sha512_h0[6];
+ ctx->h[7] = sha512_h0[7];
+#else
+ int i;
+
+ for (i = 0; i < 8; i++)
+ ctx->h[i] = sha512_h0[i];
+#endif /* UNROLL_LOOPS_SHA512 */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+static void SHA512_transform(AvbSHA512Ctx* ctx,
+ const uint8_t* message,
+ size_t block_nb) {
+ uint64_t w[80];
+ uint64_t wv[8];
+ uint64_t t1, t2;
+ const uint8_t* sub_block;
+ size_t i, j;
+
+ for (i = 0; i < block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifdef UNROLL_LOOPS_SHA512
+ PACK64(&sub_block[0], &w[0]);
+ PACK64(&sub_block[8], &w[1]);
+ PACK64(&sub_block[16], &w[2]);
+ PACK64(&sub_block[24], &w[3]);
+ PACK64(&sub_block[32], &w[4]);
+ PACK64(&sub_block[40], &w[5]);
+ PACK64(&sub_block[48], &w[6]);
+ PACK64(&sub_block[56], &w[7]);
+ PACK64(&sub_block[64], &w[8]);
+ PACK64(&sub_block[72], &w[9]);
+ PACK64(&sub_block[80], &w[10]);
+ PACK64(&sub_block[88], &w[11]);
+ PACK64(&sub_block[96], &w[12]);
+ PACK64(&sub_block[104], &w[13]);
+ PACK64(&sub_block[112], &w[14]);
+ PACK64(&sub_block[120], &w[15]);
+
+ SHA512_SCR(16);
+ SHA512_SCR(17);
+ SHA512_SCR(18);
+ SHA512_SCR(19);
+ SHA512_SCR(20);
+ SHA512_SCR(21);
+ SHA512_SCR(22);
+ SHA512_SCR(23);
+ SHA512_SCR(24);
+ SHA512_SCR(25);
+ SHA512_SCR(26);
+ SHA512_SCR(27);
+ SHA512_SCR(28);
+ SHA512_SCR(29);
+ SHA512_SCR(30);
+ SHA512_SCR(31);
+ SHA512_SCR(32);
+ SHA512_SCR(33);
+ SHA512_SCR(34);
+ SHA512_SCR(35);
+ SHA512_SCR(36);
+ SHA512_SCR(37);
+ SHA512_SCR(38);
+ SHA512_SCR(39);
+ SHA512_SCR(40);
+ SHA512_SCR(41);
+ SHA512_SCR(42);
+ SHA512_SCR(43);
+ SHA512_SCR(44);
+ SHA512_SCR(45);
+ SHA512_SCR(46);
+ SHA512_SCR(47);
+ SHA512_SCR(48);
+ SHA512_SCR(49);
+ SHA512_SCR(50);
+ SHA512_SCR(51);
+ SHA512_SCR(52);
+ SHA512_SCR(53);
+ SHA512_SCR(54);
+ SHA512_SCR(55);
+ SHA512_SCR(56);
+ SHA512_SCR(57);
+ SHA512_SCR(58);
+ SHA512_SCR(59);
+ SHA512_SCR(60);
+ SHA512_SCR(61);
+ SHA512_SCR(62);
+ SHA512_SCR(63);
+ SHA512_SCR(64);
+ SHA512_SCR(65);
+ SHA512_SCR(66);
+ SHA512_SCR(67);
+ SHA512_SCR(68);
+ SHA512_SCR(69);
+ SHA512_SCR(70);
+ SHA512_SCR(71);
+ SHA512_SCR(72);
+ SHA512_SCR(73);
+ SHA512_SCR(74);
+ SHA512_SCR(75);
+ SHA512_SCR(76);
+ SHA512_SCR(77);
+ SHA512_SCR(78);
+ SHA512_SCR(79);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
+ j++;
+ SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
+ j++;
+ SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
+ j++;
+ SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
+ j++;
+ SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
+ j++;
+ SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
+ j++;
+ SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
+ j++;
+ SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
+ j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#else
+ for (j = 0; j < 16; j++) {
+ PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] +
+ w[j];
+ t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++)
+ ctx->h[j] += wv[j];
+#endif /* UNROLL_LOOPS_SHA512 */
+ }
+}
+
+void avb_sha512_update(AvbSHA512Ctx* ctx, const uint8_t* data, size_t len) {
+ size_t block_nb;
+ size_t new_len, rem_len, tmp_len;
+ const uint8_t* shifted_data;
+
+ tmp_len = AVB_SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ avb_memcpy(&ctx->block[ctx->len], data, rem_len);
+
+ if (ctx->len + len < AVB_SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / AVB_SHA512_BLOCK_SIZE;
+
+ shifted_data = data + rem_len;
+
+ SHA512_transform(ctx, ctx->block, 1);
+ SHA512_transform(ctx, shifted_data, block_nb);
+
+ rem_len = new_len % AVB_SHA512_BLOCK_SIZE;
+
+ avb_memcpy(ctx->block, &shifted_data[block_nb << 7], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+uint8_t* avb_sha512_final(AvbSHA512Ctx* ctx) {
+ size_t block_nb;
+ size_t pm_len;
+ uint64_t len_b;
+
+#ifndef UNROLL_LOOPS_SHA512
+ size_t i;
+#endif
+
+ block_nb =
+ 1 + ((AVB_SHA512_BLOCK_SIZE - 17) < (ctx->len % AVB_SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ avb_memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK64(len_b, ctx->block + pm_len - 8);
+
+ SHA512_transform(ctx, ctx->block, block_nb);
+
+#ifdef UNROLL_LOOPS_SHA512
+ UNPACK64(ctx->h[0], &ctx->buf[0]);
+ UNPACK64(ctx->h[1], &ctx->buf[8]);
+ UNPACK64(ctx->h[2], &ctx->buf[16]);
+ UNPACK64(ctx->h[3], &ctx->buf[24]);
+ UNPACK64(ctx->h[4], &ctx->buf[32]);
+ UNPACK64(ctx->h[5], &ctx->buf[40]);
+ UNPACK64(ctx->h[6], &ctx->buf[48]);
+ UNPACK64(ctx->h[7], &ctx->buf[56]);
+#else
+ for (i = 0; i < 8; i++)
+ UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
+#endif /* UNROLL_LOOPS_SHA512 */
+
+ return ctx->buf;
+}
diff --git a/lib/libavb/avb_slot_verify.c b/lib/libavb/avb_slot_verify.c
new file mode 100644
index 00000000..c0defdf9
--- /dev/null
+++ b/lib/libavb/avb_slot_verify.c
@@ -0,0 +1,1724 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_slot_verify.h"
+#include "avb_chain_partition_descriptor.h"
+#include "avb_cmdline.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_hashtree_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+
+/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
+
+/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
+#define MAX_NUMBER_OF_VBMETA_IMAGES 32
+
+/* Maximum size of a vbmeta image - 64 KiB. */
+#define VBMETA_MAX_SIZE (64 * 1024)
+
+static AvbSlotVerifyResult initialize_persistent_digest(
+ AvbOps* ops,
+ const char* part_name,
+ const char* persistent_value_name,
+ size_t digest_size,
+ const uint8_t* initial_digest,
+ uint8_t* out_digest);
+
+/* Helper function to see if we should continue with verification in
+ * allow_verification_error=true mode if something goes wrong. See the
+ * comments for the avb_slot_verify() function for more information.
+ */
+static inline bool result_should_continue(AvbSlotVerifyResult result) {
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ return false;
+
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ return true;
+ }
+
+ return false;
+}
+
+static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
+ const char* part_name,
+ uint64_t image_size,
+ uint8_t** out_image_buf,
+ bool* out_image_preloaded) {
+ size_t part_num_read;
+ AvbIOResult io_ret;
+
+ /* Make sure that we do not overwrite existing data. */
+ avb_assert(*out_image_buf == NULL);
+ avb_assert(!*out_image_preloaded);
+
+ /* We are going to implicitly cast image_size from uint64_t to size_t in the
+ * following code, so we need to make sure that the cast is safe. */
+ if (image_size != (size_t)(image_size)) {
+ avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+
+ /* Try use a preloaded one. */
+ if (ops->get_preloaded_partition != NULL) {
+ io_ret = ops->get_preloaded_partition(
+ ops, part_name, image_size, out_image_buf, &part_num_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+
+ if (*out_image_buf != NULL) {
+ if (part_num_read != image_size) {
+ avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ *out_image_preloaded = true;
+ }
+ }
+
+ /* Allocate and copy the partition. */
+ if (!*out_image_preloaded) {
+ *out_image_buf = avb_malloc(image_size);
+ if (*out_image_buf == NULL) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+
+ io_ret = ops->read_from_partition(ops,
+ part_name,
+ 0 /* offset */,
+ image_size,
+ *out_image_buf,
+ &part_num_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ if (part_num_read != image_size) {
+ avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+ }
+
+ return AVB_SLOT_VERIFY_RESULT_OK;
+}
+
+/* Reads a persistent digest stored as a named persistent value corresponding to
+ * the given |part_name|. The value is returned in |out_digest| which must point
+ * to |expected_digest_size| bytes. If there is no digest stored for |part_name|
+ * it can be initialized by providing a non-NULL |initial_digest| of length
+ * |expected_digest_size|. This automatic initialization will only occur if the
+ * device is currently locked. The |initial_digest| may be NULL.
+ *
+ * Returns AVB_SLOT_VERIFY_RESULT_OK on success, otherwise returns an
+ * AVB_SLOT_VERIFY_RESULT_ERROR_* error code.
+ *
+ * If the value does not exist, is not supported, or is not populated, and
+ * |initial_digest| is NULL, returns
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA. If |expected_digest_size| does
+ * not match the stored digest size, also returns
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA.
+ */
+static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
+ const char* part_name,
+ size_t expected_digest_size,
+ const uint8_t* initial_digest,
+ uint8_t* out_digest) {
+ char* persistent_value_name = NULL;
+ AvbIOResult io_ret = AVB_IO_RESULT_OK;
+ size_t stored_digest_size = 0;
+
+ if (ops->read_persistent_value == NULL) {
+ avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+ persistent_value_name =
+ avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
+ if (persistent_value_name == NULL) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+
+ io_ret = ops->read_persistent_value(ops,
+ persistent_value_name,
+ expected_digest_size,
+ out_digest,
+ &stored_digest_size);
+
+ // If no such named persistent value exists and an initial digest value was
+ // given, initialize the named persistent value with the given digest. If
+ // initialized successfully, this will recurse into this function but with a
+ // NULL initial_digest.
+ if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE && initial_digest) {
+ AvbSlotVerifyResult ret =
+ initialize_persistent_digest(ops,
+ part_name,
+ persistent_value_name,
+ expected_digest_size,
+ initial_digest,
+ out_digest);
+ avb_free(persistent_value_name);
+ return ret;
+ }
+ avb_free(persistent_value_name);
+
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
+ // Treat a missing persistent value as a verification error, which is
+ // ignoreable, rather than a metadata error which is not.
+ avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+ } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
+ io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE) {
+ avb_errorv(
+ part_name, ": Persistent digest is not of expected size.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ } else if (expected_digest_size != stored_digest_size) {
+ avb_errorv(
+ part_name, ": Persistent digest is not of expected size.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ }
+ return AVB_SLOT_VERIFY_RESULT_OK;
+}
+
+static AvbSlotVerifyResult initialize_persistent_digest(
+ AvbOps* ops,
+ const char* part_name,
+ const char* persistent_value_name,
+ size_t digest_size,
+ const uint8_t* initial_digest,
+ uint8_t* out_digest) {
+ AvbSlotVerifyResult ret;
+ AvbIOResult io_ret = AVB_IO_RESULT_OK;
+ bool is_device_unlocked = true;
+
+ io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting device lock state.\n");
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+
+ if (is_device_unlocked) {
+ avb_debugv(part_name,
+ ": Digest does not exist, device unlocked so not initializing "
+ "digest.\n",
+ NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+ }
+
+ // Device locked; initialize digest with given initial value.
+ avb_debugv(part_name,
+ ": Digest does not exist, initializing persistent digest.\n",
+ NULL);
+ io_ret = ops->write_persistent_value(
+ ops, persistent_value_name, digest_size, initial_digest);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error initializing persistent digest.\n", NULL);
+ return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ }
+
+ // To ensure that the digest value was written successfully - and avoid a
+ // scenario where the digest is simply 'initialized' on every verify - recurse
+ // into read_persistent_digest to read back the written value. The NULL
+ // initial_digest ensures that this will not recurse again.
+ ret = read_persistent_digest(ops, part_name, digest_size, NULL, out_digest);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ avb_errorv(part_name,
+ ": Reading back initialized persistent digest failed!\n",
+ NULL);
+ }
+ return ret;
+}
+
+static AvbSlotVerifyResult load_and_verify_hash_partition(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ bool allow_verification_error,
+ const AvbDescriptor* descriptor,
+ AvbSlotVerifyData* slot_data) {
+ AvbHashDescriptor hash_desc;
+ const uint8_t* desc_partition_name = NULL;
+ const uint8_t* desc_salt;
+ const uint8_t* desc_digest;
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ AvbSlotVerifyResult ret;
+ AvbIOResult io_ret;
+ uint8_t* image_buf = NULL;
+ bool image_preloaded = false;
+ uint8_t* digest;
+ size_t digest_len;
+ const char* found;
+ uint64_t image_size;
+ size_t expected_digest_len = 0;
+ uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
+ const uint8_t* expected_digest = NULL;
+
+ if (!avb_hash_descriptor_validate_and_byteswap(
+ (const AvbHashDescriptor*)descriptor, &hash_desc)) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ desc_partition_name =
+ ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
+ desc_salt = desc_partition_name + hash_desc.partition_name_len;
+ desc_digest = desc_salt + hash_desc.salt_len;
+
+ if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Don't bother loading or validating unless the partition was
+ * requested in the first place.
+ */
+ found = avb_strv_find_str(requested_partitions,
+ (const char*)desc_partition_name,
+ hash_desc.partition_name_len);
+ if (found == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+ goto out;
+ }
+
+ if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
+ /* No ab_suffix, just copy the partition name as is. */
+ if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
+ avb_error("Partition name does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
+ part_name[hash_desc.partition_name_len] = '\0';
+ } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
+ /* No ab_suffix allowed for partitions without a digest in the descriptor
+ * because these partitions hold data unique to this device and are not
+ * updated using an A/B scheme.
+ */
+ avb_error("Cannot use A/B with a persistent digest.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ } else {
+ /* Add ab_suffix to the partition name. */
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ (const char*)desc_partition_name,
+ hash_desc.partition_name_len,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ }
+
+ /* If we're allowing verification errors then hash_desc.image_size
+ * may no longer match what's in the partition... so in this case
+ * just load the entire partition.
+ *
+ * For example, this can happen if a developer does 'fastboot flash
+ * boot /path/to/new/and/bigger/boot.img'. We want this to work
+ * since it's such a common workflow.
+ */
+ image_size = hash_desc.image_size;
+ if (allow_verification_error) {
+ io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+ }
+
+ ret = load_full_partition(
+ ops, part_name, image_size, &image_buf, &image_preloaded);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+ // Although only one of the type might be used, we have to defined the
+ // structure here so that they would live outside the 'if/else' scope to be
+ // used later.
+ AvbSHA256Ctx sha256_ctx;
+ AvbSHA512Ctx sha512_ctx;
+ size_t image_size_to_hash = hash_desc.image_size;
+ // If we allow verification error and the whole partition is smaller than
+ // image size in hash descriptor, we just hash the whole partition.
+ if (image_size_to_hash > image_size) {
+ image_size_to_hash = image_size;
+ }
+ if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
+ avb_sha256_init(&sha256_ctx);
+ avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
+ avb_sha256_update(&sha256_ctx, image_buf, image_size_to_hash);
+ digest = avb_sha256_final(&sha256_ctx);
+ digest_len = AVB_SHA256_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
+ avb_sha512_init(&sha512_ctx);
+ avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
+ avb_sha512_update(&sha512_ctx, image_buf, image_size_to_hash);
+ digest = avb_sha512_final(&sha512_ctx);
+ digest_len = AVB_SHA512_DIGEST_SIZE;
+ } else {
+ avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ if (hash_desc.digest_len == 0) {
+ /* Expect a match to a persistent digest. */
+ avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
+ expected_digest_len = digest_len;
+ expected_digest = expected_digest_buf;
+ avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
+ /* Pass |digest| as the |initial_digest| so devices not yet initialized get
+ * initialized to the current partition digest.
+ */
+ ret = read_persistent_digest(
+ ops, part_name, digest_len, digest, expected_digest_buf);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+ } else {
+ /* Expect a match to the digest in the descriptor. */
+ expected_digest_len = hash_desc.digest_len;
+ expected_digest = desc_digest;
+ }
+
+ if (digest_len != expected_digest_len) {
+ avb_errorv(
+ part_name, ": Digest in descriptor not of expected size.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
+ avb_errorv(part_name,
+ ": Hash of data does not match digest in descriptor.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+ goto out;
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+
+ /* If it worked and something was loaded, copy to slot_data. */
+ if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
+ image_buf != NULL) {
+ AvbPartitionData* loaded_partition;
+ if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
+ avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ loaded_partition =
+ &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+ loaded_partition->partition_name = avb_strdup(found);
+ loaded_partition->data_size = image_size;
+ loaded_partition->data = image_buf;
+ loaded_partition->preloaded = image_preloaded;
+ image_buf = NULL;
+ }
+
+fail:
+ if (image_buf != NULL && !image_preloaded) {
+ avb_free(image_buf);
+ }
+ return ret;
+}
+
+static AvbSlotVerifyResult load_requested_partitions(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyData* slot_data) {
+ AvbSlotVerifyResult ret;
+ uint8_t* image_buf = NULL;
+ bool image_preloaded = false;
+ size_t n;
+
+ for (n = 0; requested_partitions[n] != NULL; n++) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ AvbIOResult io_ret;
+ uint64_t image_size;
+ AvbPartitionData* loaded_partition;
+
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+
+ ret = load_full_partition(
+ ops, part_name, image_size, &image_buf, &image_preloaded);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+
+ /* Move to slot_data. */
+ if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
+ avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ loaded_partition =
+ &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
+ loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
+ if (loaded_partition->partition_name == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ loaded_partition->data_size = image_size;
+ loaded_partition->data = image_buf; /* Transferring the owner. */
+ loaded_partition->preloaded = image_preloaded;
+ image_buf = NULL;
+ image_preloaded = false;
+ }
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+out:
+ /* Free the current buffer if any. */
+ if (image_buf != NULL && !image_preloaded) {
+ avb_free(image_buf);
+ }
+ /* Buffers that are already saved in slot_data will be handled by the caller
+ * even on failure. */
+ return ret;
+}
+
+static AvbSlotVerifyResult load_and_verify_vbmeta(
+ AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
+ bool allow_verification_error,
+ AvbVBMetaImageFlags toplevel_vbmeta_flags,
+ int rollback_index_location,
+ const char* partition_name,
+ size_t partition_name_len,
+ const uint8_t* expected_public_key,
+ size_t expected_public_key_length,
+ AvbSlotVerifyData* slot_data,
+ AvbAlgorithmType* out_algorithm_type,
+ AvbCmdlineSubstList* out_additional_cmdline_subst) {
+ char full_partition_name[AVB_PART_NAME_MAX_SIZE];
+ AvbSlotVerifyResult ret;
+ AvbIOResult io_ret;
+ size_t vbmeta_offset;
+ size_t vbmeta_size;
+ uint8_t* vbmeta_buf = NULL;
+ size_t vbmeta_num_read;
+ AvbVBMetaVerifyResult vbmeta_ret;
+ const uint8_t* pk_data;
+ size_t pk_len;
+ AvbVBMetaImageHeader vbmeta_header;
+ uint64_t stored_rollback_index;
+ const AvbDescriptor** descriptors = NULL;
+ size_t num_descriptors;
+ size_t n;
+ bool is_main_vbmeta;
+ bool look_for_vbmeta_footer;
+ AvbVBMetaData* vbmeta_image_data = NULL;
+
+ ret = AVB_SLOT_VERIFY_RESULT_OK;
+
+ avb_assert(slot_data != NULL);
+
+ /* Since we allow top-level vbmeta in 'boot', use
+ * rollback_index_location to determine whether we're the main
+ * vbmeta struct.
+ */
+ is_main_vbmeta = false;
+ if (rollback_index_location == 0) {
+ if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
+ is_main_vbmeta = true;
+ }
+ }
+
+ /* Don't use footers for vbmeta partitions ('vbmeta' or
+ * 'vbmeta_<partition_name>').
+ */
+ look_for_vbmeta_footer = true;
+ if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
+ look_for_vbmeta_footer = false;
+ }
+
+ if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Construct full partition name e.g. system_a. */
+ if (!avb_str_concat(full_partition_name,
+ sizeof full_partition_name,
+ partition_name,
+ partition_name_len,
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("Partition name and suffix does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* If we're loading from the main vbmeta partition, the vbmeta struct is in
+ * the beginning. Otherwise we may have to locate it via a footer... if no
+ * footer is found, we look in the beginning to support e.g. vbmeta_<org>
+ * partitions holding data for e.g. super partitions (b/80195851 for
+ * rationale).
+ */
+ vbmeta_offset = 0;
+ vbmeta_size = VBMETA_MAX_SIZE;
+ if (look_for_vbmeta_footer) {
+ uint8_t footer_buf[AVB_FOOTER_SIZE];
+ size_t footer_num_read;
+ AvbFooter footer;
+
+ io_ret = ops->read_from_partition(ops,
+ full_partition_name,
+ -AVB_FOOTER_SIZE,
+ AVB_FOOTER_SIZE,
+ footer_buf,
+ &footer_num_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ avb_assert(footer_num_read == AVB_FOOTER_SIZE);
+
+ if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
+ &footer)) {
+ avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
+ } else {
+ /* Basic footer sanity check since the data is untrusted. */
+ if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
+ avb_errorv(
+ full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
+ } else {
+ vbmeta_offset = footer.vbmeta_offset;
+ vbmeta_size = footer.vbmeta_size;
+ }
+ }
+ }
+
+ vbmeta_buf = avb_malloc(vbmeta_size);
+ if (vbmeta_buf == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+
+ if (vbmeta_offset != 0) {
+ avb_debugv("Loading vbmeta struct in footer from partition '",
+ full_partition_name,
+ "'.\n",
+ NULL);
+ } else {
+ avb_debugv("Loading vbmeta struct from partition '",
+ full_partition_name,
+ "'.\n",
+ NULL);
+ }
+
+ io_ret = ops->read_from_partition(ops,
+ full_partition_name,
+ vbmeta_offset,
+ vbmeta_size,
+ vbmeta_buf,
+ &vbmeta_num_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ /* If we're looking for 'vbmeta' but there is no such partition,
+ * go try to get it from the boot partition instead.
+ */
+ if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
+ !look_for_vbmeta_footer) {
+ avb_debugv(full_partition_name,
+ ": No such partition. Trying 'boot' instead.\n",
+ NULL);
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "boot",
+ avb_strlen("boot"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ out_algorithm_type,
+ out_additional_cmdline_subst);
+ goto out;
+ } else {
+ avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ }
+ avb_assert(vbmeta_num_read <= vbmeta_size);
+
+ /* Check if the image is properly signed and get the public key used
+ * to sign the image.
+ */
+ vbmeta_ret =
+ avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
+ switch (vbmeta_ret) {
+ case AVB_VBMETA_VERIFY_RESULT_OK:
+ avb_assert(pk_data != NULL && pk_len > 0);
+ break;
+
+ case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+ case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
+ case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+ avb_errorv(full_partition_name,
+ ": Error verifying vbmeta image: ",
+ avb_vbmeta_verify_result_to_string(vbmeta_ret),
+ "\n",
+ NULL);
+ if (!allow_verification_error) {
+ goto out;
+ }
+ break;
+
+ case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
+ /* No way to continue this case. */
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ avb_errorv(full_partition_name,
+ ": Error verifying vbmeta image: invalid vbmeta header\n",
+ NULL);
+ goto out;
+
+ case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
+ /* No way to continue this case. */
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
+ avb_errorv(full_partition_name,
+ ": Error verifying vbmeta image: unsupported AVB version\n",
+ NULL);
+ goto out;
+ }
+
+ /* Byteswap the header. */
+ avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
+ &vbmeta_header);
+
+ /* If we're the toplevel, assign flags so they'll be passed down. */
+ if (is_main_vbmeta) {
+ toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
+ } else {
+ if (vbmeta_header.flags != 0) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ avb_errorv(full_partition_name,
+ ": chained vbmeta image has non-zero flags\n",
+ NULL);
+ goto out;
+ }
+ }
+
+ uint32_t rollback_index_location_to_use = rollback_index_location;
+
+ /* Check if key used to make signature matches what is expected. */
+ if (pk_data != NULL) {
+ if (expected_public_key != NULL) {
+ avb_assert(!is_main_vbmeta);
+ if (expected_public_key_length != pk_len ||
+ avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
+ avb_errorv(full_partition_name,
+ ": Public key used to sign data does not match key in chain "
+ "partition descriptor.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+ } else {
+ bool key_is_trusted = false;
+ const uint8_t* pk_metadata = NULL;
+ size_t pk_metadata_len = 0;
+
+ if (vbmeta_header.public_key_metadata_size > 0) {
+ pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
+ vbmeta_header.authentication_data_block_size +
+ vbmeta_header.public_key_metadata_offset;
+ pk_metadata_len = vbmeta_header.public_key_metadata_size;
+ }
+
+ // If we're not using a vbmeta partition, need to use another AvbOps...
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ io_ret = ops->validate_public_key_for_partition(
+ ops,
+ full_partition_name,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted,
+ &rollback_index_location_to_use);
+ } else {
+ avb_assert(is_main_vbmeta);
+ io_ret = ops->validate_vbmeta_public_key(ops,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted);
+ }
+
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(full_partition_name,
+ ": Error while checking public key used to sign data.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (!key_is_trusted) {
+ avb_errorv(full_partition_name,
+ ": Public key used to sign data rejected.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* Check rollback index. */
+ io_ret = ops->read_rollback_index(
+ ops, rollback_index_location_to_use, &stored_rollback_index);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(full_partition_name,
+ ": Error getting rollback index for location.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (vbmeta_header.rollback_index < stored_rollback_index) {
+ avb_errorv(
+ full_partition_name,
+ ": Image rollback index is less than the stored rollback index.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
+ if (!allow_verification_error) {
+ goto out;
+ }
+ }
+
+ /* Copy vbmeta to vbmeta_images before recursing. */
+ if (is_main_vbmeta) {
+ avb_assert(slot_data->num_vbmeta_images == 0);
+ } else {
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ avb_assert(slot_data->num_vbmeta_images > 0);
+ }
+ }
+ if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
+ avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
+ vbmeta_image_data->partition_name = avb_strdup(partition_name);
+ vbmeta_image_data->vbmeta_data = vbmeta_buf;
+ /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
+ * and this includes data past the end of the image. Pass the
+ * actual size of the vbmeta image. Also, no need to use
+ * avb_safe_add() since the header has already been verified.
+ */
+ vbmeta_image_data->vbmeta_size =
+ sizeof(AvbVBMetaImageHeader) +
+ vbmeta_header.authentication_data_block_size +
+ vbmeta_header.auxiliary_data_block_size;
+ vbmeta_image_data->verify_result = vbmeta_ret;
+
+ /* If verification has been disabled by setting a bit in the image,
+ * we're done... except that we need to load the entirety of the
+ * requested partitions.
+ */
+ if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+ AvbSlotVerifyResult sub_ret;
+ avb_debugv(
+ full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
+ /* If load_requested_partitions() fail it is always a fatal
+ * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
+ * than recoverable (e.g. one where result_should_continue()
+ * returns true) and we want to convey that error.
+ */
+ sub_ret = load_requested_partitions(
+ ops, requested_partitions, ab_suffix, slot_data);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ }
+ goto out;
+ }
+
+ /* Now go through all descriptors and take the appropriate action:
+ *
+ * - hash descriptor: Load data from partition, calculate hash, and
+ * checks that it matches what's in the hash descriptor.
+ *
+ * - hashtree descriptor: Do nothing since verification happens
+ * on-the-fly from within the OS. (Unless the descriptor uses a
+ * persistent digest, in which case we need to find it).
+ *
+ * - chained partition descriptor: Load the footer, load the vbmeta
+ * image, verify vbmeta image (includes rollback checks, hash
+ * checks, bail on chained partitions).
+ */
+ descriptors =
+ avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
+ for (n = 0; n < num_descriptors; n++) {
+ AvbDescriptor desc;
+
+ if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
+ avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ switch (desc.tag) {
+ case AVB_DESCRIPTOR_TAG_HASH: {
+ AvbSlotVerifyResult sub_ret;
+ sub_ret = load_and_verify_hash_partition(ops,
+ requested_partitions,
+ ab_suffix,
+ allow_verification_error,
+ descriptors[n],
+ slot_data);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ if (!allow_verification_error || !result_should_continue(ret)) {
+ goto out;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
+ AvbSlotVerifyResult sub_ret;
+ AvbChainPartitionDescriptor chain_desc;
+ const uint8_t* chain_partition_name;
+ const uint8_t* chain_public_key;
+
+ /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
+ if (!is_main_vbmeta) {
+ avb_errorv(full_partition_name,
+ ": Encountered chain descriptor not in main image.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ if (!avb_chain_partition_descriptor_validate_and_byteswap(
+ (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
+ avb_errorv(full_partition_name,
+ ": Chain partition descriptor is invalid.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ if (chain_desc.rollback_index_location == 0) {
+ avb_errorv(full_partition_name,
+ ": Chain partition has invalid "
+ "rollback_index_location field.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ chain_partition_name = ((const uint8_t*)descriptors[n]) +
+ sizeof(AvbChainPartitionDescriptor);
+ chain_public_key = chain_partition_name + chain_desc.partition_name_len;
+
+ sub_ret =
+ load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ toplevel_vbmeta_flags,
+ chain_desc.rollback_index_location,
+ (const char*)chain_partition_name,
+ chain_desc.partition_name_len,
+ chain_public_key,
+ chain_desc.public_key_len,
+ slot_data,
+ NULL, /* out_algorithm_type */
+ NULL /* out_additional_cmdline_subst */);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ if (!result_should_continue(ret)) {
+ goto out;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
+ const uint8_t* kernel_cmdline;
+ AvbKernelCmdlineDescriptor kernel_cmdline_desc;
+ bool apply_cmdline;
+
+ if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
+ (AvbKernelCmdlineDescriptor*)descriptors[n],
+ &kernel_cmdline_desc)) {
+ avb_errorv(full_partition_name,
+ ": Kernel cmdline descriptor is invalid.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ kernel_cmdline = ((const uint8_t*)descriptors[n]) +
+ sizeof(AvbKernelCmdlineDescriptor);
+
+ if (!avb_validate_utf8(kernel_cmdline,
+ kernel_cmdline_desc.kernel_cmdline_length)) {
+ avb_errorv(full_partition_name,
+ ": Kernel cmdline is not valid UTF-8.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* Compare the flags for top-level VBMeta struct with flags in
+ * the command-line descriptor so command-line snippets only
+ * intended for a certain mode (dm-verity enabled/disabled)
+ * are skipped if applicable.
+ */
+ apply_cmdline = true;
+ if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
+ if (kernel_cmdline_desc.flags &
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
+ apply_cmdline = false;
+ }
+ } else {
+ if (kernel_cmdline_desc.flags &
+ AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
+ apply_cmdline = false;
+ }
+ }
+
+ if (apply_cmdline) {
+ if (slot_data->cmdline == NULL) {
+ slot_data->cmdline =
+ avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ avb_memcpy(slot_data->cmdline,
+ kernel_cmdline,
+ kernel_cmdline_desc.kernel_cmdline_length);
+ } else {
+ /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
+ size_t orig_size = avb_strlen(slot_data->cmdline);
+ size_t new_size =
+ orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
+ char* new_cmdline = avb_calloc(new_size);
+ if (new_cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
+ new_cmdline[orig_size] = ' ';
+ avb_memcpy(new_cmdline + orig_size + 1,
+ kernel_cmdline,
+ kernel_cmdline_desc.kernel_cmdline_length);
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_cmdline;
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_HASHTREE: {
+ AvbHashtreeDescriptor hashtree_desc;
+
+ if (!avb_hashtree_descriptor_validate_and_byteswap(
+ (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
+ avb_errorv(
+ full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* We only need to continue when there is no digest in the descriptor.
+ * This is because the only processing here is to find the digest and
+ * make it available on the kernel command line.
+ */
+ if (hashtree_desc.root_digest_len == 0) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ size_t digest_len = 0;
+ uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
+ const uint8_t* desc_partition_name =
+ ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
+
+ if (!avb_validate_utf8(desc_partition_name,
+ hashtree_desc.partition_name_len)) {
+ avb_error("Partition name is not valid UTF-8.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ /* No ab_suffix for partitions without a digest in the descriptor
+ * because these partitions hold data unique to this device and are
+ * not updated using an A/B scheme.
+ */
+ if ((hashtree_desc.flags &
+ AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
+ avb_strlen(ab_suffix) != 0) {
+ avb_error("Cannot use A/B with a persistent root digest.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
+ avb_error("Partition name does not fit.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+ avb_memcpy(
+ part_name, desc_partition_name, hashtree_desc.partition_name_len);
+ part_name[hashtree_desc.partition_name_len] = '\0';
+
+ /* Determine the expected digest size from the hash algorithm. */
+ if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
+ 0) {
+ digest_len = AVB_SHA1_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
+ "sha256") == 0) {
+ digest_len = AVB_SHA256_DIGEST_SIZE;
+ } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
+ "sha512") == 0) {
+ digest_len = AVB_SHA512_DIGEST_SIZE;
+ } else {
+ avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ ret = read_persistent_digest(ops,
+ part_name,
+ digest_len,
+ NULL /* initial_digest */,
+ digest_buf);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+
+ if (out_additional_cmdline_subst) {
+ ret =
+ avb_add_root_digest_substitution(part_name,
+ digest_buf,
+ digest_len,
+ out_additional_cmdline_subst);
+ if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto out;
+ }
+ }
+ }
+ } break;
+
+ case AVB_DESCRIPTOR_TAG_PROPERTY:
+ /* Do nothing. */
+ break;
+ }
+ }
+
+ if (rollback_index_location < 0 ||
+ rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
+ avb_errorv(
+ full_partition_name, ": Invalid rollback_index_location.\n", NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+ goto out;
+ }
+
+ slot_data->rollback_indexes[rollback_index_location] =
+ vbmeta_header.rollback_index;
+
+ if (out_algorithm_type != NULL) {
+ *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
+ }
+
+out:
+ /* If |vbmeta_image_data| isn't NULL it means that it adopted
+ * |vbmeta_buf| so in that case don't free it here.
+ */
+ if (vbmeta_image_data == NULL) {
+ if (vbmeta_buf != NULL) {
+ avb_free(vbmeta_buf);
+ }
+ }
+ if (descriptors != NULL) {
+ avb_free(descriptors);
+ }
+ return ret;
+}
+
+static AvbIOResult avb_manage_hashtree_error_mode(
+ AvbOps* ops,
+ AvbSlotVerifyFlags flags,
+ AvbSlotVerifyData* data,
+ AvbHashtreeErrorMode* out_hashtree_error_mode) {
+ AvbHashtreeErrorMode ret = AVB_HASHTREE_ERROR_MODE_RESTART;
+ AvbIOResult io_ret = AVB_IO_RESULT_OK;
+ uint8_t vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
+ uint8_t stored_vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
+ size_t num_bytes_read;
+
+ avb_assert(out_hashtree_error_mode != NULL);
+ avb_assert(ops->read_persistent_value != NULL);
+ avb_assert(ops->write_persistent_value != NULL);
+
+ // If we're rebooting because of dm-verity corruption, make a note of
+ // the vbmeta hash so we can stay in 'eio' mode until things change.
+ if (flags & AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION) {
+ avb_debug(
+ "Rebooting because of dm-verity corruption - "
+ "recording OS instance and using 'eio' mode.\n");
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
+ io_ret = ops->write_persistent_value(ops,
+ AVB_NPV_MANAGED_VERITY_MODE,
+ AVB_SHA256_DIGEST_SIZE,
+ vbmeta_digest_sha256);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error writing to " AVB_NPV_MANAGED_VERITY_MODE ".\n");
+ goto out;
+ }
+ ret = AVB_HASHTREE_ERROR_MODE_EIO;
+ io_ret = AVB_IO_RESULT_OK;
+ goto out;
+ }
+
+ // See if we're in 'eio' mode.
+ io_ret = ops->read_persistent_value(ops,
+ AVB_NPV_MANAGED_VERITY_MODE,
+ AVB_SHA256_DIGEST_SIZE,
+ stored_vbmeta_digest_sha256,
+ &num_bytes_read);
+ if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE ||
+ (io_ret == AVB_IO_RESULT_OK && num_bytes_read == 0)) {
+ // This is the usual case ('eio' mode not set).
+ avb_debug("No dm-verity corruption - using in 'restart' mode.\n");
+ ret = AVB_HASHTREE_ERROR_MODE_RESTART;
+ io_ret = AVB_IO_RESULT_OK;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE ".\n");
+ goto out;
+ }
+ if (num_bytes_read != AVB_SHA256_DIGEST_SIZE) {
+ avb_error(
+ "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
+ ".\n");
+ io_ret = AVB_IO_RESULT_ERROR_IO;
+ goto out;
+ }
+
+ // OK, so we're currently in 'eio' mode and the vbmeta digest of the OS
+ // that caused this is in |stored_vbmeta_digest_sha256| ... now see if
+ // the OS we're dealing with now is the same.
+ avb_slot_verify_data_calculate_vbmeta_digest(
+ data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
+ if (avb_memcmp(vbmeta_digest_sha256,
+ stored_vbmeta_digest_sha256,
+ AVB_SHA256_DIGEST_SIZE) == 0) {
+ // It's the same so we're still in 'eio' mode.
+ avb_debug("Same OS instance detected - staying in 'eio' mode.\n");
+ ret = AVB_HASHTREE_ERROR_MODE_EIO;
+ io_ret = AVB_IO_RESULT_OK;
+ } else {
+ // It did change!
+ avb_debug(
+ "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
+ io_ret =
+ ops->write_persistent_value(ops,
+ AVB_NPV_MANAGED_VERITY_MODE,
+ 0, // This clears the persistent property.
+ vbmeta_digest_sha256);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error clearing " AVB_NPV_MANAGED_VERITY_MODE ".\n");
+ goto out;
+ }
+ ret = AVB_HASHTREE_ERROR_MODE_RESTART;
+ io_ret = AVB_IO_RESULT_OK;
+ }
+
+out:
+ *out_hashtree_error_mode = ret;
+ return io_ret;
+}
+
+static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
+ char part_name[AVB_PART_NAME_MAX_SIZE];
+ char* system_part_name = "system";
+ char guid_buf[37];
+ AvbIOResult io_ret;
+
+ if (!avb_str_concat(part_name,
+ sizeof part_name,
+ system_part_name,
+ avb_strlen(system_part_name),
+ ab_suffix,
+ avb_strlen(ab_suffix))) {
+ avb_error("System partition name and suffix does not fit.\n");
+ return false;
+ }
+
+ io_ret = ops->get_unique_guid_for_partition(
+ ops, part_name, guid_buf, sizeof guid_buf);
+ if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+ avb_debug("No system partition.\n");
+ return false;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_error("Error getting unique GUID for system partition.\n");
+ return false;
+ }
+
+ return true;
+}
+
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data) {
+ AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ AvbSlotVerifyData* slot_data = NULL;
+ AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
+ bool using_boot_for_vbmeta = false;
+ AvbVBMetaImageHeader toplevel_vbmeta;
+ bool allow_verification_error =
+ (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+ AvbCmdlineSubstList* additional_cmdline_subst = NULL;
+
+ /* Fail early if we're missing the AvbOps needed for slot verification. */
+ avb_assert(ops->read_is_device_unlocked != NULL);
+ avb_assert(ops->read_from_partition != NULL);
+ avb_assert(ops->get_size_of_partition != NULL);
+ avb_assert(ops->read_rollback_index != NULL);
+ avb_assert(ops->get_unique_guid_for_partition != NULL);
+
+ if (out_data != NULL) {
+ *out_data = NULL;
+ }
+
+ /* Allowing dm-verity errors defeats the purpose of verified boot so
+ * only allow this if set up to allow verification errors
+ * (e.g. typically only UNLOCKED mode).
+ */
+ if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
+ !allow_verification_error) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* Make sure passed-in AvbOps support persistent values if
+ * asking for libavb to manage verity state.
+ */
+ if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
+ if (ops->read_persistent_value == NULL ||
+ ops->write_persistent_value == NULL) {
+ avb_error(
+ "Persistent values required for "
+ "AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO "
+ "but are not implemented in given AvbOps.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ }
+
+ /* Make sure passed-in AvbOps support verifying public keys and getting
+ * rollback index location if not using a vbmeta partition.
+ */
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (ops->validate_public_key_for_partition == NULL) {
+ avb_error(
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
+ "validate_public_key_for_partition() operation isn't implemented.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ } else {
+ avb_assert(ops->validate_vbmeta_public_key != NULL);
+ }
+
+ slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
+ if (slot_data == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ slot_data->vbmeta_images =
+ avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
+ if (slot_data->vbmeta_images == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ slot_data->loaded_partitions =
+ avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
+ if (slot_data->loaded_partitions == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
+ additional_cmdline_subst = avb_new_cmdline_subst_list();
+ if (additional_cmdline_subst == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (requested_partitions == NULL || requested_partitions[0] == NULL) {
+ avb_fatal(
+ "Requested partitions cannot be empty when using "
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* No vbmeta partition, go through each of the requested partitions... */
+ for (size_t n = 0; requested_partitions[n] != NULL; n++) {
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type,
+ additional_cmdline_subst);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ } else {
+ /* Usual path, load "vbmeta"... */
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "vbmeta",
+ avb_strlen("vbmeta"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type,
+ additional_cmdline_subst);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ if (!result_should_continue(ret)) {
+ goto fail;
+ }
+
+ /* If things check out, mangle the kernel command-line as needed. */
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
+ avb_assert(
+ avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
+ using_boot_for_vbmeta = true;
+ }
+ }
+
+ /* Byteswap top-level vbmeta header since we'll need it below. */
+ avb_vbmeta_image_header_to_host_byte_order(
+ (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
+ &toplevel_vbmeta);
+
+ /* Fill in |ab_suffix| field. */
+ slot_data->ab_suffix = avb_strdup(ab_suffix);
+ if (slot_data->ab_suffix == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
+ /* If verification is disabled, we are done ... we specifically
+ * don't want to add any androidboot.* options since verification
+ * is disabled.
+ */
+ if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+ /* Since verification is disabled we didn't process any
+ * descriptors and thus there's no cmdline... so set root= such
+ * that the system partition is mounted.
+ */
+ avb_assert(slot_data->cmdline == NULL);
+ // Devices with dynamic partitions won't have system partition.
+ // Instead, it has a large super partition to accommodate *.img files.
+ // See b/119551429 for details.
+ if (has_system_partition(ops, ab_suffix)) {
+ slot_data->cmdline =
+ avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+ } else {
+ // The |cmdline| field should be a NUL-terminated string.
+ slot_data->cmdline = avb_strdup("");
+ }
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ } else {
+ /* If requested, manage dm-verity mode... */
+ AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
+ if (hashtree_error_mode ==
+ AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
+ AvbIOResult io_ret;
+ io_ret = avb_manage_hashtree_error_mode(
+ ops, flags, slot_data, &resolved_hashtree_error_mode);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+ goto fail;
+ }
+ }
+ slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
+
+ /* Add options... */
+ AvbSlotVerifyResult sub_ret;
+ sub_ret = avb_append_options(ops,
+ flags,
+ slot_data,
+ &toplevel_vbmeta,
+ algorithm_type,
+ hashtree_error_mode,
+ resolved_hashtree_error_mode);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ goto fail;
+ }
+ }
+
+ /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
+ if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
+ char* new_cmdline;
+ new_cmdline = avb_sub_cmdline(ops,
+ slot_data->cmdline,
+ ab_suffix,
+ using_boot_for_vbmeta,
+ additional_cmdline_subst);
+ if (new_cmdline != slot_data->cmdline) {
+ if (new_cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_cmdline;
+ }
+ }
+
+ if (out_data != NULL) {
+ *out_data = slot_data;
+ } else {
+ avb_slot_verify_data_free(slot_data);
+ }
+
+ avb_free_cmdline_subst_list(additional_cmdline_subst);
+ additional_cmdline_subst = NULL;
+
+ if (!allow_verification_error) {
+ avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
+ }
+
+ return ret;
+
+fail:
+ if (slot_data != NULL) {
+ avb_slot_verify_data_free(slot_data);
+ }
+ if (additional_cmdline_subst != NULL) {
+ avb_free_cmdline_subst_list(additional_cmdline_subst);
+ }
+ return ret;
+}
+
+void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
+ if (data->ab_suffix != NULL) {
+ avb_free(data->ab_suffix);
+ }
+ if (data->cmdline != NULL) {
+ avb_free(data->cmdline);
+ }
+ if (data->vbmeta_images != NULL) {
+ size_t n;
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
+ if (vbmeta_image->partition_name != NULL) {
+ avb_free(vbmeta_image->partition_name);
+ }
+ if (vbmeta_image->vbmeta_data != NULL) {
+ avb_free(vbmeta_image->vbmeta_data);
+ }
+ }
+ avb_free(data->vbmeta_images);
+ }
+ if (data->loaded_partitions != NULL) {
+ size_t n;
+ for (n = 0; n < data->num_loaded_partitions; n++) {
+ AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
+ if (loaded_partition->partition_name != NULL) {
+ avb_free(loaded_partition->partition_name);
+ }
+ if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
+ avb_free(loaded_partition->data);
+ }
+ }
+ avb_free(data->loaded_partitions);
+ }
+ avb_free(data);
+}
+
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ ret = "OK";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ ret = "ERROR_OOM";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ ret = "ERROR_IO";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ ret = "ERROR_VERIFICATION";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ ret = "ERROR_ROLLBACK_INDEX";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ ret = "ERROR_PUBLIC_KEY_REJECTED";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ ret = "ERROR_INVALID_METADATA";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ ret = "ERROR_UNSUPPORTED_VERSION";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ ret = "ERROR_INVALID_ARGUMENT";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbSlotVerifyResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}
+
+void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
+ AvbDigestType digest_type,
+ uint8_t* out_digest) {
+ bool ret = false;
+ size_t n;
+
+ switch (digest_type) {
+ case AVB_DIGEST_TYPE_SHA256: {
+ AvbSHA256Ctx ctx;
+ avb_sha256_init(&ctx);
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ avb_sha256_update(&ctx,
+ data->vbmeta_images[n].vbmeta_data,
+ data->vbmeta_images[n].vbmeta_size);
+ }
+ avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
+ ret = true;
+ } break;
+
+ case AVB_DIGEST_TYPE_SHA512: {
+ AvbSHA512Ctx ctx;
+ avb_sha512_init(&ctx);
+ for (n = 0; n < data->num_vbmeta_images; n++) {
+ avb_sha512_update(&ctx,
+ data->vbmeta_images[n].vbmeta_data,
+ data->vbmeta_images[n].vbmeta_size);
+ }
+ avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
+ ret = true;
+ } break;
+
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (!ret) {
+ avb_fatal("Unknown digest type");
+ }
+}
diff --git a/lib/libavb/avb_slot_verify.h b/lib/libavb/avb_slot_verify.h
new file mode 100644
index 00000000..8d0fa536
--- /dev/null
+++ b/lib/libavb/avb_slot_verify.h
@@ -0,0 +1,381 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SLOT_VERIFY_H_
+#define AVB_SLOT_VERIFY_H_
+
+#include "avb_ops.h"
+#include "avb_vbmeta_image.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return codes used in avb_slot_verify(), see that function for
+ * documentation for each field.
+ *
+ * Use avb_slot_verify_result_to_string() to get a textual
+ * representation usable for error/debug output.
+ */
+typedef enum {
+ AVB_SLOT_VERIFY_RESULT_OK,
+ AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
+ AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
+ AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
+ AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
+ AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
+ AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
+} AvbSlotVerifyResult;
+
+/* Various error handling modes for when verification fails using a
+ * hashtree at runtime inside the HLOS.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE means that the OS
+ * will invalidate the current slot and restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_RESTART means that the OS will restart.
+ *
+ * AVB_HASHTREE_ERROR_MODE_EIO means that an EIO error will be
+ * returned to applications.
+ *
+ * AVB_HASHTREE_ERROR_MODE_LOGGING means that errors will be logged
+ * and corrupt data may be returned to applications. This mode should
+ * be used ONLY for diagnostics and debugging. It cannot be used
+ * unless AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is also
+ * used.
+ *
+ * AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO means that either
+ * AVB_HASHTREE_ERROR_MODE_RESTART or AVB_HASHTREE_ERROR_MODE_EIO is used
+ * depending on state. This mode implements a state machine whereby
+ * AVB_HASHTREE_ERROR_MODE_RESTART is used by default and when
+ * AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION is passed the
+ * mode transitions to AVB_HASHTREE_ERROR_MODE_EIO. When a new OS has been
+ * detected the device transitions back to the AVB_HASHTREE_ERROR_MODE_RESTART
+ * mode. To do this persistent storage is needed - specifically this means that
+ * the passed in AvbOps will need to have the read_persistent_value() and
+ * write_persistent_value() operations implemented. The name of the persistent
+ * value used is "avb.managed_verity_mode" and 32 bytes of storage is needed.
+ */
+typedef enum {
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ AVB_HASHTREE_ERROR_MODE_RESTART,
+ AVB_HASHTREE_ERROR_MODE_EIO,
+ AVB_HASHTREE_ERROR_MODE_LOGGING,
+ AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
+} AvbHashtreeErrorMode;
+
+/* Flags that influence how avb_slot_verify() works.
+ *
+ * If AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is NOT set then
+ * avb_slot_verify() will bail out as soon as an error is encountered
+ * and |out_data| is set only if AVB_SLOT_VERIFY_RESULT_OK is
+ * returned.
+ *
+ * Otherwise if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set
+ * avb_slot_verify() will continue verification efforts and |out_data|
+ * is also set if AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION, or
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned. It is
+ * undefined which error is returned if more than one distinct error
+ * is encountered. It is guaranteed that AVB_SLOT_VERIFY_RESULT_OK is
+ * returned if, and only if, there are no errors. This mode is needed
+ * to boot valid but unverified slots when the device is unlocked.
+ *
+ * Also, if AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR is set the
+ * contents loaded from |requested_partition| will be the contents of
+ * the entire partition instead of just the size specified in the hash
+ * descriptor.
+ *
+ * The AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION flag
+ * should be set if using AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
+ * and the reason the boot loader is running is because the device
+ * was restarted by the dm-verity driver.
+ *
+ * If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
+ * data won't be loaded from the "vbmeta" partition and the
+ * |validate_vbmeta_public_key| operation is never called. Instead, the
+ * vbmeta structs in |requested_partitions| are loaded and processed and the
+ * |validate_public_key_for_partition| operation is called for each of these
+ * vbmeta structs. This flag is useful when booting into recovery on a device
+ * not using A/B - see section "Booting into recovery" in README.md for
+ * more information.
+ */
+typedef enum {
+ AVB_SLOT_VERIFY_FLAGS_NONE = 0,
+ AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
+ AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
+} AvbSlotVerifyFlags;
+
+/* Get a textual representation of |result|. */
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result);
+
+/* Maximum number of rollback index locations supported. */
+#define AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS 32
+
+/* AvbPartitionData contains data loaded from partitions when using
+ * avb_slot_verify(). The |partition_name| field contains the name of
+ * the partition (without A/B suffix), |data| points to the loaded
+ * data which is |data_size| bytes long. If |preloaded| is set to true,
+ * this structure dose not own |data|. The caller of |avb_slot_verify|
+ * needs to make sure that the preloaded data outlives this
+ * |AvbPartitionData| structure.
+ *
+ * Note that this is strictly less than the partition size - it's only
+ * the image stored there, not the entire partition nor any of the
+ * metadata.
+ */
+typedef struct {
+ char* partition_name;
+ uint8_t* data;
+ size_t data_size;
+ bool preloaded;
+} AvbPartitionData;
+
+/* AvbVBMetaData contains a vbmeta struct loaded from a partition when
+ * using avb_slot_verify(). The |partition_name| field contains the
+ * name of the partition (without A/B suffix), |vbmeta_data| points to
+ * the loaded data which is |vbmeta_size| bytes long.
+ *
+ * The |verify_result| field contains the result of
+ * avb_vbmeta_image_verify() on the data. This is guaranteed to be
+ * AVB_VBMETA_VERIFY_RESULT_OK for all vbmeta images if
+ * avb_slot_verify() returns AVB_SLOT_VERIFY_RESULT_OK.
+ *
+ * You can use avb_descriptor_get_all(), avb_descriptor_foreach(), and
+ * avb_vbmeta_image_header_to_host_byte_order() with this data.
+ */
+typedef struct {
+ char* partition_name;
+ uint8_t* vbmeta_data;
+ size_t vbmeta_size;
+ AvbVBMetaVerifyResult verify_result;
+} AvbVBMetaData;
+
+/* AvbSlotVerifyData contains data needed to boot a particular slot
+ * and is returned by avb_slot_verify() if partitions in a slot are
+ * successfully verified.
+ *
+ * All data pointed to by this struct - including data in each item in
+ * the |partitions| array - will be freed when the
+ * avb_slot_verify_data_free() function is called.
+ *
+ * The |ab_suffix| field is the copy of the of |ab_suffix| field
+ * passed to avb_slot_verify(). It is the A/B suffix of the slot. This
+ * value includes the leading underscore - typical values are "" (if
+ * no slots are in use), "_a" (for the first slot), and "_b" (for the
+ * second slot).
+ *
+ * The VBMeta images that were checked are available in the
+ * |vbmeta_images| field. The field |num_vbmeta_images| contains the
+ * number of elements in this array. The first element -
+ * vbmeta_images[0] - is guaranteed to be from the partition with the
+ * top-level vbmeta struct. This is usually the "vbmeta" partition in
+ * the requested slot but if there is no "vbmeta" partition it can
+ * also be the "boot" partition.
+ *
+ * The partitions loaded and verified from from the slot are
+ * accessible in the |loaded_partitions| array. The field
+ * |num_loaded_partitions| contains the number of elements in this
+ * array. The order of partitions in this array may not necessarily be
+ * the same order as in the passed-in |requested_partitions| array.
+ *
+ * Rollback indexes for the verified slot are stored in the
+ * |rollback_indexes| field. Note that avb_slot_verify() will NEVER
+ * modify stored_rollback_index[n] locations e.g. it will never use
+ * the write_rollback_index() AvbOps operation. Instead it is the job
+ * of the caller of avb_slot_verify() to do this based on e.g. A/B
+ * policy and other factors. See libavb_ab/avb_ab_flow.c for an
+ * example of how to do this.
+ *
+ * The |cmdline| field is a NUL-terminated string in UTF-8 resulting
+ * from concatenating all |AvbKernelCmdlineDescriptor| and then
+ * performing proper substitution of the variables
+ * $(ANDROID_SYSTEM_PARTUUID), $(ANDROID_BOOT_PARTUUID), and
+ * $(ANDROID_VBMETA_PARTUUID) using the
+ * get_unique_guid_for_partition() operation in |AvbOps|. Additionally
+ * $(ANDROID_VERITY_MODE) will be replaced with the proper dm-verity
+ * option depending on the value of |hashtree_error_mode|.
+ *
+ * Additionally, the |cmdline| field will have the following kernel
+ * command-line options set (unless verification is disabled, see
+ * below):
+ *
+ * androidboot.veritymode: This is set to 'disabled' if the
+ * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in top-level
+ * vbmeta struct. Otherwise it is set to 'enforcing' if the
+ * passed-in hashtree error mode is AVB_HASHTREE_ERROR_MODE_RESTART
+ * or AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 'eio' if it's
+ * set to AVB_HASHTREE_ERROR_MODE_EIO, and 'logging' if it's set to
+ * AVB_HASHTREE_ERROR_MODE_LOGGING.
+ *
+ * androidboot.veritymode.managed: This is set to 'yes' only
+ * if hashtree validation isn't disabled and the passed-in hashtree
+ * error mode is AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO.
+ *
+ * androidboot.vbmeta.invalidate_on_error: This is set to 'yes' only
+ * if hashtree validation isn't disabled and the passed-in hashtree
+ * error mode is AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE.
+ *
+ * androidboot.vbmeta.device_state: set to "locked" or "unlocked"
+ * depending on the result of the result of AvbOps's
+ * read_is_unlocked() function.
+ *
+ * androidboot.vbmeta.{hash_alg, size, digest}: Will be set to
+ * the digest of all images in |vbmeta_images|.
+ *
+ * androidboot.vbmeta.device: This is set to the value
+ * PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
+ * will end up pointing to the vbmeta partition for the verified
+ * slot. If there is no vbmeta partition it will point to the boot
+ * partition of the verified slot. If the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
+ * set.
+ *
+ * androidboot.vbmeta.avb_version: This is set to the decimal value
+ * of AVB_VERSION_MAJOR followed by a dot followed by the decimal
+ * value of AVB_VERSION_MINOR, for example "1.0" or "1.4". This
+ * version number represents the vbmeta file format version
+ * supported by libavb copy used in the boot loader. This is not
+ * necessarily the same version number of the on-disk metadata for
+ * the slot that was verified.
+ *
+ * Note that androidboot.slot_suffix is not set in the |cmdline| field
+ * in |AvbSlotVerifyData| - you will have to set this yourself.
+ *
+ * If the |AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED| flag is set
+ * in the top-level vbmeta struct then only the top-level vbmeta
+ * struct is verified and descriptors will not processed. The return
+ * value will be set accordingly (if this flag is set via 'avbctl
+ * disable-verification' then the return value will be
+ * |AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION|) and
+ * |AvbSlotVerifyData| is returned. Additionally all partitions in the
+ * |requested_partitions| are loaded and the |cmdline| field is set to
+ * "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)" and the GUID for the
+ * appropriate system partition is substituted in. Note that none of
+ * the androidboot.* options mentioned above will be set.
+ *
+ * The |resolved_hashtree_error_mode| is the the value of the passed
+ * avb_slot_verify()'s |hashtree_error_mode| parameter except that it never has
+ * the value AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO. If this value was
+ * passed in, then the restart/eio state machine is used resulting in
+ * |resolved_hashtree_error_mode| being set to either
+ * AVB_HASHTREE_ERROR_MODE_RESTART or AVB_HASHTREE_ERROR_MODE_EIO. If set to
+ * AVB_HASHTREE_ERROR_MODE_EIO the boot loader should present a RED warning
+ * screen for the user to click through before continuing to boot.
+ *
+ * This struct may grow in the future without it being considered an
+ * ABI break.
+ */
+typedef struct {
+ char* ab_suffix;
+ AvbVBMetaData* vbmeta_images;
+ size_t num_vbmeta_images;
+ AvbPartitionData* loaded_partitions;
+ size_t num_loaded_partitions;
+ char* cmdline;
+ uint64_t rollback_indexes[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS];
+ AvbHashtreeErrorMode resolved_hashtree_error_mode;
+} AvbSlotVerifyData;
+
+/* Calculates a digest of all vbmeta images in |data| using
+ * the digest indicated by |digest_type|. Stores the result
+ * in |out_digest| which must be large enough to hold a digest
+ * of the requested type.
+ */
+void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
+ AvbDigestType digest_type,
+ uint8_t* out_digest);
+
+/* Frees a |AvbSlotVerifyData| including all data it points to. */
+void avb_slot_verify_data_free(AvbSlotVerifyData* data);
+
+/* Performs a full verification of the slot identified by |ab_suffix|
+ * and load and verify the contents of the partitions whose name is in
+ * the NULL-terminated string array |requested_partitions| (each
+ * partition must use hash verification). If not using A/B, pass an
+ * empty string (e.g. "", not NULL) for |ab_suffix|. This parameter
+ * must include the leading underscore, for example "_a" should be
+ * used to refer to the first slot.
+ *
+ * Typically the |requested_partitions| array only contains a single
+ * item for the boot partition, 'boot'.
+ *
+ * Verification includes loading and verifying data from the 'vbmeta',
+ * the requested hash partitions, and possibly other partitions (with
+ * |ab_suffix| appended), inspecting rollback indexes, and checking if
+ * the public key used to sign the data is acceptable. The functions
+ * in |ops| will be used to do this.
+ *
+ * If |out_data| is not NULL, it will be set to a newly allocated
+ * |AvbSlotVerifyData| struct containing all the data needed to
+ * actually boot the slot. This data structure should be freed with
+ * avb_slot_verify_data_free() when you are done with it. See below
+ * for when this is returned.
+ *
+ * The |flags| parameter is used to influence the semantics of
+ * avb_slot_verify() - for example the
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR flag can be used to
+ * ignore verification errors which is something needed in the
+ * UNLOCKED state. See the AvbSlotVerifyFlags enumeration for details.
+ *
+ * The |hashtree_error_mode| parameter should be set to the desired error
+ * handling mode. See the AvbHashtreeErrorMode enumeration for details.
+ *
+ * Also note that |out_data| is never set if
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM, AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ * or AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned.
+ *
+ * AVB_SLOT_VERIFY_RESULT_OK is returned if everything is verified
+ * correctly and all public keys are accepted.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED is returned if
+ * everything is verified correctly out but one or more public keys
+ * are not accepted. This includes the case where integrity data is
+ * not signed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_OOM is returned if unable to
+ * allocate memory.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_IO is returned if an I/O error
+ * occurred while trying to load data or get a rollback index.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION is returned if the data
+ * did not verify, e.g. the digest didn't match or signature checks
+ * failed.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX is returned if a
+ * rollback index was less than its stored value.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA is returned if some
+ * of the metadata is invalid or inconsistent.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION is returned if
+ * some of the metadata requires a newer version of libavb than what
+ * is in use.
+ *
+ * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT is returned if the
+ * caller passed invalid parameters, for example trying to use
+ * AVB_HASHTREE_ERROR_MODE_LOGGING without
+ * AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR.
+ */
+AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
+ const char* const* requested_partitions,
+ const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SLOT_VERIFY_H_ */
diff --git a/lib/libavb/avb_sysdeps.h b/lib/libavb/avb_sysdeps.h
new file mode 100644
index 00000000..f52428cc
--- /dev/null
+++ b/lib/libavb/avb_sysdeps.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_SYSDEPS_H_
+#define AVB_SYSDEPS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Change these includes to match your platform to bring in the
+ * equivalent types available in a normal C runtime. At least things
+ * like uint8_t, uint64_t, and bool (with |false|, |true| keywords)
+ * must be present.
+ */
+#include <common.h>
+
+/* If you don't have gcc or clang, these attribute macros may need to
+ * be adjusted.
+ */
+#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#define AVB_ATTR_PACKED __attribute__((packed))
+#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
+#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
+
+/* Size in bytes used for alignment. */
+#ifdef __LP64__
+#define AVB_ALIGNMENT_SIZE 8
+#else
+#define AVB_ALIGNMENT_SIZE 4
+#endif
+
+/* Compare |n| bytes in |src1| and |src2|.
+ *
+ * Returns an integer less than, equal to, or greater than zero if the
+ * first |n| bytes of |src1| is found, respectively, to be less than,
+ * to match, or be greater than the first |n| bytes of |src2|. */
+int avb_memcmp(const void* src1,
+ const void* src2,
+ size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare two strings.
+ *
+ * Return an integer less than, equal to, or greater than zero if |s1|
+ * is found, respectively, to be less than, to match, or be greater
+ * than |s2|.
+ */
+int avb_strcmp(const char* s1, const char* s2);
+
+/* Compare |n| bytes in two strings.
+ *
+ * Return an integer less than, equal to, or greater than zero if the
+ * first |n| bytes of |s1| is found, respectively, to be less than,
+ * to match, or be greater than the first |n| bytes of |s2|.
+ */
+int avb_strncmp(const char* s1, const char* s2, size_t n);
+
+/* Copy |n| bytes from |src| to |dest|. */
+void* avb_memcpy(void* dest, const void* src, size_t n);
+
+/* Set |n| bytes starting at |s| to |c|. Returns |dest|. */
+void* avb_memset(void* dest, const int c, size_t n);
+
+/* Prints out a message. The string passed must be a NUL-terminated
+ * UTF-8 string.
+ */
+void avb_print(const char* message);
+
+/* Prints out a vector of strings. Each argument must point to a
+ * NUL-terminated UTF-8 string and NULL should be the last argument.
+ */
+void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
+
+/* Aborts the program or reboots the device. */
+void avb_abort(void) AVB_ATTR_NO_RETURN;
+
+/* Allocates |size| bytes. Returns NULL if no memory is available,
+ * otherwise a pointer to the allocated memory.
+ *
+ * The memory is not initialized.
+ *
+ * The pointer returned is guaranteed to be word-aligned.
+ *
+ * The memory should be freed with avb_free() when you are done with it.
+ */
+void* avb_malloc_(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Frees memory previously allocated with avb_malloc(). */
+void avb_free(void* ptr);
+
+/* Returns the lenght of |str|, excluding the terminating NUL-byte. */
+size_t avb_strlen(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Divide the |dividend| by 10 and saves back to the pointer. Return the
+ * remainder. */
+uint32_t avb_div_by_10(uint64_t* dividend);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_SYSDEPS_H_ */
diff --git a/lib/libavb/avb_sysdeps_posix.c b/lib/libavb/avb_sysdeps_posix.c
new file mode 100644
index 00000000..4ccf41e4
--- /dev/null
+++ b/lib/libavb/avb_sysdeps_posix.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "avb_sysdeps.h"
+
+int avb_memcmp(const void* src1, const void* src2, size_t n) {
+ return memcmp(src1, src2, n);
+}
+
+void* avb_memcpy(void* dest, const void* src, size_t n) {
+ return memcpy(dest, src, n);
+}
+
+void* avb_memset(void* dest, const int c, size_t n) {
+ return memset(dest, c, n);
+}
+
+int avb_strcmp(const char* s1, const char* s2) {
+ return strcmp(s1, s2);
+}
+
+int avb_strncmp(const char* s1, const char* s2, size_t n) {
+ return strncmp(s1, s2, n);
+}
+
+size_t avb_strlen(const char* str) {
+ return strlen(str);
+}
+
+void avb_abort(void) {
+ hang();
+}
+
+void avb_print(const char* message) {
+ printf("%s", message);
+}
+
+void avb_printv(const char* message, ...) {
+ va_list ap;
+ const char* m;
+
+ va_start(ap, message);
+ for (m = message; m != NULL; m = va_arg(ap, const char*)) {
+ printf("%s", m);
+ }
+ va_end(ap);
+}
+
+void* avb_malloc_(size_t size) {
+ return malloc(size);
+}
+
+void avb_free(void* ptr) {
+ free(ptr);
+}
+
+uint32_t avb_div_by_10(uint64_t* dividend) {
+ uint32_t rem = (uint32_t)(*dividend % 10);
+ *dividend /= 10;
+ return rem;
+}
diff --git a/lib/libavb/avb_util.c b/lib/libavb/avb_util.c
new file mode 100644
index 00000000..405d6253
--- /dev/null
+++ b/lib/libavb/avb_util.c
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_util.h"
+
+#include <stdarg.h>
+
+uint32_t avb_be32toh(uint32_t in) {
+ uint8_t* d = (uint8_t*)&in;
+ uint32_t ret;
+ ret = ((uint32_t)d[0]) << 24;
+ ret |= ((uint32_t)d[1]) << 16;
+ ret |= ((uint32_t)d[2]) << 8;
+ ret |= ((uint32_t)d[3]);
+ return ret;
+}
+
+uint64_t avb_be64toh(uint64_t in) {
+ uint8_t* d = (uint8_t*)&in;
+ uint64_t ret;
+ ret = ((uint64_t)d[0]) << 56;
+ ret |= ((uint64_t)d[1]) << 48;
+ ret |= ((uint64_t)d[2]) << 40;
+ ret |= ((uint64_t)d[3]) << 32;
+ ret |= ((uint64_t)d[4]) << 24;
+ ret |= ((uint64_t)d[5]) << 16;
+ ret |= ((uint64_t)d[6]) << 8;
+ ret |= ((uint64_t)d[7]);
+ return ret;
+}
+
+/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) {
+ union {
+ uint32_t word;
+ uint8_t bytes[4];
+ } ret;
+ ret.bytes[0] = (in >> 24) & 0xff;
+ ret.bytes[1] = (in >> 16) & 0xff;
+ ret.bytes[2] = (in >> 8) & 0xff;
+ ret.bytes[3] = in & 0xff;
+ return ret.word;
+}
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) {
+ union {
+ uint64_t word;
+ uint8_t bytes[8];
+ } ret;
+ ret.bytes[0] = (in >> 56) & 0xff;
+ ret.bytes[1] = (in >> 48) & 0xff;
+ ret.bytes[2] = (in >> 40) & 0xff;
+ ret.bytes[3] = (in >> 32) & 0xff;
+ ret.bytes[4] = (in >> 24) & 0xff;
+ ret.bytes[5] = (in >> 16) & 0xff;
+ ret.bytes[6] = (in >> 8) & 0xff;
+ ret.bytes[7] = in & 0xff;
+ return ret.word;
+}
+
+int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
+ const unsigned char* us1 = s1;
+ const unsigned char* us2 = s2;
+ int result = 0;
+
+ if (0 == n) {
+ return 0;
+ }
+
+ /*
+ * Code snippet without data-dependent branch due to Nate Lawson
+ * (nate@root.org) of Root Labs.
+ */
+ while (n--) {
+ result |= *us1++ ^ *us2++;
+ }
+
+ return result != 0;
+}
+
+bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
+ uint64_t original_value;
+
+ avb_assert(value != NULL);
+
+ original_value = *value;
+
+ *value += value_to_add;
+ if (*value < original_value) {
+ avb_error("Overflow when adding values.\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
+ uint64_t dummy;
+ if (out_result == NULL) {
+ out_result = &dummy;
+ }
+ *out_result = a;
+ return avb_safe_add_to(out_result, b);
+}
+
+bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
+ size_t n;
+ unsigned int num_cc;
+
+ for (n = 0, num_cc = 0; n < num_bytes; n++) {
+ uint8_t c = data[n];
+
+ if (num_cc > 0) {
+ if ((c & (0x80 | 0x40)) == 0x80) {
+ /* 10xx xxxx */
+ } else {
+ goto fail;
+ }
+ num_cc--;
+ } else {
+ if (c < 0x80) {
+ num_cc = 0;
+ } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
+ /* 110x xxxx */
+ num_cc = 1;
+ } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
+ /* 1110 xxxx */
+ num_cc = 2;
+ } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
+ (0x80 | 0x40 | 0x20 | 0x10)) {
+ /* 1111 0xxx */
+ num_cc = 3;
+ } else {
+ goto fail;
+ }
+ }
+ }
+
+ if (num_cc != 0) {
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ return false;
+}
+
+bool avb_str_concat(char* buf,
+ size_t buf_size,
+ const char* str1,
+ size_t str1_len,
+ const char* str2,
+ size_t str2_len) {
+ uint64_t combined_len;
+
+ if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
+ avb_error("Overflow when adding string sizes.\n");
+ return false;
+ }
+
+ if (combined_len > buf_size - 1) {
+ avb_error("Insufficient buffer space.\n");
+ return false;
+ }
+
+ avb_memcpy(buf, str1, str1_len);
+ avb_memcpy(buf + str1_len, str2, str2_len);
+ buf[combined_len] = '\0';
+
+ return true;
+}
+
+void* avb_malloc(size_t size) {
+ void* ret = avb_malloc_(size);
+ if (ret == NULL) {
+ avb_error("Failed to allocate memory.\n");
+ return NULL;
+ }
+ return ret;
+}
+
+void* avb_calloc(size_t size) {
+ void* ret = avb_malloc(size);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ avb_memset(ret, '\0', size);
+ return ret;
+}
+
+char* avb_strdup(const char* str) {
+ size_t len = avb_strlen(str);
+ char* ret = avb_malloc(len + 1);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ avb_memcpy(ret, str, len);
+ ret[len] = '\0';
+
+ return ret;
+}
+
+const char* avb_strstr(const char* haystack, const char* needle) {
+ size_t n, m;
+
+ /* Look through |haystack| and check if the first character of
+ * |needle| matches. If so, check the rest of |needle|.
+ */
+ for (n = 0; haystack[n] != '\0'; n++) {
+ if (haystack[n] != needle[0]) {
+ continue;
+ }
+
+ for (m = 1;; m++) {
+ if (needle[m] == '\0') {
+ return haystack + n;
+ }
+
+ if (haystack[n + m] != needle[m]) {
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char* avb_strv_find_str(const char* const* strings,
+ const char* str,
+ size_t str_size) {
+ size_t n;
+ for (n = 0; strings[n] != NULL; n++) {
+ if (avb_strlen(strings[n]) == str_size &&
+ avb_memcmp(strings[n], str, str_size) == 0) {
+ return strings[n];
+ }
+ }
+ return NULL;
+}
+
+char* avb_replace(const char* str, const char* search, const char* replace) {
+ char* ret = NULL;
+ size_t ret_len = 0;
+ size_t search_len, replace_len;
+ const char* str_after_last_replace;
+
+ search_len = avb_strlen(search);
+ replace_len = avb_strlen(replace);
+
+ str_after_last_replace = str;
+ while (*str != '\0') {
+ const char* s;
+ size_t num_before;
+ size_t num_new;
+
+ s = avb_strstr(str, search);
+ if (s == NULL) {
+ break;
+ }
+
+ num_before = s - str;
+
+ if (ret == NULL) {
+ num_new = num_before + replace_len + 1;
+ ret = avb_malloc(num_new);
+ if (ret == NULL) {
+ goto out;
+ }
+ avb_memcpy(ret, str, num_before);
+ avb_memcpy(ret + num_before, replace, replace_len);
+ ret[num_new - 1] = '\0';
+ ret_len = num_new - 1;
+ } else {
+ char* new_str;
+ num_new = ret_len + num_before + replace_len + 1;
+ new_str = avb_malloc(num_new);
+ if (new_str == NULL) {
+ goto out;
+ }
+ avb_memcpy(new_str, ret, ret_len);
+ avb_memcpy(new_str + ret_len, str, num_before);
+ avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
+ new_str[num_new - 1] = '\0';
+ avb_free(ret);
+ ret = new_str;
+ ret_len = num_new - 1;
+ }
+
+ str = s + search_len;
+ str_after_last_replace = str;
+ }
+
+ if (ret == NULL) {
+ ret = avb_strdup(str_after_last_replace);
+ if (ret == NULL) {
+ goto out;
+ }
+ } else {
+ size_t num_remaining = avb_strlen(str_after_last_replace);
+ size_t num_new = ret_len + num_remaining + 1;
+ char* new_str = avb_malloc(num_new);
+ if (new_str == NULL) {
+ goto out;
+ }
+ avb_memcpy(new_str, ret, ret_len);
+ avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
+ new_str[num_new - 1] = '\0';
+ avb_free(ret);
+ ret = new_str;
+ ret_len = num_new - 1;
+ }
+
+out:
+ return ret;
+}
+
+/* We only support a limited amount of strings in avb_strdupv(). */
+#define AVB_STRDUPV_MAX_NUM_STRINGS 32
+
+char* avb_strdupv(const char* str, ...) {
+ va_list ap;
+ const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
+ size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
+ size_t num_strings, n;
+ uint64_t total_length;
+ char *ret = NULL, *dest;
+
+ num_strings = 0;
+ total_length = 0;
+ va_start(ap, str);
+ do {
+ size_t str_len = avb_strlen(str);
+ strings[num_strings] = str;
+ lengths[num_strings] = str_len;
+ if (!avb_safe_add_to(&total_length, str_len)) {
+ avb_fatal("Overflow while determining total length.\n");
+ break;
+ }
+ num_strings++;
+ if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
+ avb_fatal("Too many strings passed.\n");
+ break;
+ }
+ str = va_arg(ap, const char*);
+ } while (str != NULL);
+ va_end(ap);
+
+ ret = avb_malloc(total_length + 1);
+ if (ret == NULL) {
+ goto out;
+ }
+
+ dest = ret;
+ for (n = 0; n < num_strings; n++) {
+ avb_memcpy(dest, strings[n], lengths[n]);
+ dest += lengths[n];
+ }
+ *dest = '\0';
+ avb_assert(dest == ret + total_length);
+
+out:
+ return ret;
+}
+
+const char* avb_basename(const char* str) {
+ int64_t n;
+ size_t len;
+
+ len = avb_strlen(str);
+ if (len >= 2) {
+ for (n = len - 2; n >= 0; n--) {
+ if (str[n] == '/') {
+ return str + n + 1;
+ }
+ }
+ }
+ return str;
+}
+
+void avb_uppercase(char* str) {
+ size_t i;
+ for (i = 0; str[i] != '\0'; ++i) {
+ if (str[i] <= 0x7A && str[i] >= 0x61) {
+ str[i] -= 0x20;
+ }
+ }
+}
+
+char* avb_bin2hex(const uint8_t* data, size_t data_len) {
+ const char hex_digits[17] = "0123456789abcdef";
+ char* hex_data;
+ size_t n;
+
+ hex_data = avb_malloc(data_len * 2 + 1);
+ if (hex_data == NULL) {
+ return NULL;
+ }
+
+ for (n = 0; n < data_len; n++) {
+ hex_data[n * 2] = hex_digits[data[n] >> 4];
+ hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
+ }
+ hex_data[n * 2] = '\0';
+ return hex_data;
+}
diff --git a/lib/libavb/avb_util.h b/lib/libavb/avb_util.h
new file mode 100644
index 00000000..26dc6b04
--- /dev/null
+++ b/lib/libavb/avb_util.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_UTIL_H_
+#define AVB_UTIL_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AVB_STRINGIFY(x) #x
+#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+
+#ifdef AVB_ENABLE_DEBUG
+/* Aborts the program if |expr| is false.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_assert(expr) \
+ do { \
+ if (!(expr)) { \
+ avb_fatal("assert fail: " #expr "\n"); \
+ } \
+ } while (0)
+#else
+#define avb_assert(expr)
+#endif
+
+/* Aborts the program if reached.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#ifdef AVB_ENABLE_DEBUG
+#define avb_assert_not_reached() \
+ do { \
+ avb_fatal("assert_not_reached()\n"); \
+ } while (0)
+#else
+#define avb_assert_not_reached()
+#endif
+
+/* Aborts the program if |addr| is not word-aligned.
+ *
+ * This has no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_assert_aligned(addr) \
+ avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
+
+#ifdef AVB_ENABLE_DEBUG
+/* Print functions, used for diagnostics.
+ *
+ * These have no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_debug(message) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": DEBUG: ", \
+ message, \
+ NULL); \
+ } while (0)
+#define avb_debugv(message, ...) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": DEBUG: ", \
+ message, \
+ ##__VA_ARGS__); \
+ } while (0)
+#else
+#define avb_debug(message)
+#define avb_debugv(message, ...)
+#endif
+
+/* Prints out a message. This is typically used if a runtime-error
+ * occurs.
+ */
+#define avb_error(message) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": ERROR: ", \
+ message, \
+ NULL); \
+ } while (0)
+#define avb_errorv(message, ...) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": ERROR: ", \
+ message, \
+ ##__VA_ARGS__); \
+ } while (0)
+
+/* Prints out a message and calls avb_abort().
+ */
+#define avb_fatal(message) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": FATAL: ", \
+ message, \
+ NULL); \
+ avb_abort(); \
+ } while (0)
+#define avb_fatalv(message, ...) \
+ do { \
+ avb_printv(avb_basename(__FILE__), \
+ ":", \
+ AVB_TO_STRING(__LINE__), \
+ ": FATAL: ", \
+ message, \
+ ##__VA_ARGS__); \
+ avb_abort(); \
+ } while (0)
+
+/* Converts a 32-bit unsigned integer from big-endian to host byte order. */
+uint32_t avb_be32toh(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 64-bit unsigned integer from big-endian to host byte order. */
+uint64_t avb_be64toh(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
+uint32_t avb_htobe32(uint32_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
+uint64_t avb_htobe64(uint64_t in) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Compare |n| bytes starting at |s1| with |s2| and return 0 if they
+ * match, 1 if they don't. Returns 0 if |n|==0, since no bytes
+ * mismatched.
+ *
+ * Time taken to perform the comparison is only dependent on |n| and
+ * not on the relationship of the match between |s1| and |s2|.
+ *
+ * Note that unlike avb_memcmp(), this only indicates inequality, not
+ * whether |s1| is less than or greater than |s2|.
+ */
+int avb_safe_memcmp(const void* s1,
+ const void* s2,
+ size_t n) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |value_to_add| to |value| with overflow protection.
+ *
+ * Returns false if the addition overflows, true otherwise. In either
+ * case, |value| is always modified.
+ */
+bool avb_safe_add_to(uint64_t* value,
+ uint64_t value_to_add) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Adds |a| and |b| with overflow protection, returning the value in
+ * |out_result|.
+ *
+ * It's permissible to pass NULL for |out_result| if you just want to
+ * check that the addition would not overflow.
+ *
+ * Returns false if the addition overflows, true otherwise.
+ */
+bool avb_safe_add(uint64_t* out_result,
+ uint64_t a,
+ uint64_t b) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Checks if |num_bytes| data at |data| is a valid UTF-8
+ * string. Returns true if valid UTF-8, false otherwise.
+ */
+bool avb_validate_utf8(const uint8_t* data,
+ size_t num_bytes) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Concatenates |str1| (of |str1_len| bytes) and |str2| (of |str2_len|
+ * bytes) and puts the result in |buf| which holds |buf_size|
+ * bytes. The result is also guaranteed to be NUL terminated. Fail if
+ * there is not enough room in |buf| for the resulting string plus
+ * terminating NUL byte.
+ *
+ * Returns true if the operation succeeds, false otherwise.
+ */
+bool avb_str_concat(char* buf,
+ size_t buf_size,
+ const char* str1,
+ size_t str1_len,
+ const char* str2,
+ size_t str2_len);
+
+/* Like avb_malloc_() but prints a error using avb_error() if memory
+ * allocation fails.
+ */
+void* avb_malloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Like avb_malloc() but sets the memory with zeroes. */
+void* avb_calloc(size_t size) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NUL-terminated string. Returns NULL on OOM. */
+char* avb_strdup(const char* str) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Duplicates a NULL-terminated array of NUL-terminated strings by
+ * concatenating them. The returned string will be
+ * NUL-terminated. Returns NULL on OOM.
+ */
+char* avb_strdupv(const char* str,
+ ...) AVB_ATTR_WARN_UNUSED_RESULT AVB_ATTR_SENTINEL;
+
+/* Finds the first occurrence of |needle| in the string |haystack|
+ * where both strings are NUL-terminated strings. The terminating NUL
+ * bytes are not compared.
+ *
+ * Returns NULL if not found, otherwise points into |haystack| for the
+ * first occurrence of |needle|.
+ */
+const char* avb_strstr(const char* haystack,
+ const char* needle) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Finds the first occurrence of |str| in the NULL-terminated string
+ * array |strings|. Each element in |strings| must be
+ * NUL-terminated. The string given by |str| need not be
+ * NUL-terminated but its size must be given in |str_size|.
+ *
+ * Returns NULL if not found, otherwise points into |strings| for the
+ * first occurrence of |str|.
+ */
+const char* avb_strv_find_str(const char* const* strings,
+ const char* str,
+ size_t str_size);
+
+/* Replaces all occurrences of |search| with |replace| in |str|.
+ *
+ * Returns a newly allocated string or NULL if out of memory.
+ */
+char* avb_replace(const char* str,
+ const char* search,
+ const char* replace) AVB_ATTR_WARN_UNUSED_RESULT;
+
+/* Calculates the CRC-32 for data in |buf| of size |buf_size|. */
+uint32_t avb_crc32(const uint8_t* buf, size_t buf_size);
+
+/* Returns the basename of |str|. This is defined as the last path
+ * component, assuming the normal POSIX separator '/'. If there are no
+ * separators, returns |str|.
+ */
+const char* avb_basename(const char* str);
+
+/* Converts any ascii lowercase characters in |str| to uppercase in-place.
+ * |str| must be NUL-terminated and valid UTF-8.
+ */
+void avb_uppercase(char* str);
+
+/* Converts |data_len| bytes of |data| to hex and returns the result. Returns
+ * NULL on OOM. Caller must free the returned string with avb_free.
+ */
+char* avb_bin2hex(const uint8_t* data, size_t data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_UTIL_H_ */
diff --git a/lib/libavb/avb_vbmeta_image.c b/lib/libavb/avb_vbmeta_image.c
new file mode 100644
index 00000000..384f5ac1
--- /dev/null
+++ b/lib/libavb/avb_vbmeta_image.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#include "avb_vbmeta_image.h"
+#include "avb_crypto.h"
+#include "avb_rsa.h"
+#include "avb_sha.h"
+#include "avb_util.h"
+#include "avb_version.h"
+
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+ const uint8_t* data,
+ size_t length,
+ const uint8_t** out_public_key_data,
+ size_t* out_public_key_length) {
+ AvbVBMetaVerifyResult ret;
+ AvbVBMetaImageHeader h;
+ uint8_t* computed_hash;
+ const AvbAlgorithmData* algorithm;
+ AvbSHA256Ctx sha256_ctx;
+ AvbSHA512Ctx sha512_ctx;
+ const uint8_t* header_block;
+ const uint8_t* authentication_block;
+ const uint8_t* auxiliary_block;
+ int verification_result;
+
+ ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
+
+ if (out_public_key_data != NULL) {
+ *out_public_key_data = NULL;
+ }
+ if (out_public_key_length != NULL) {
+ *out_public_key_length = 0;
+ }
+
+ /* Before we byteswap or compare Magic, ensure length is long enough. */
+ if (length < sizeof(AvbVBMetaImageHeader)) {
+ avb_error("Length is smaller than header.\n");
+ goto out;
+ }
+
+ /* Ensure magic is correct. */
+ if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
+ avb_error("Magic is incorrect.\n");
+ goto out;
+ }
+
+ avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
+ &h);
+
+ /* Ensure we don't attempt to access any fields if we do not meet
+ * the specified minimum version of libavb.
+ */
+ if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
+ (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
+ avb_error("Mismatch between image version and libavb version.\n");
+ ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
+ goto out;
+ }
+
+ /* Ensure |release_string| ends with a NUL byte. */
+ if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
+ avb_error("Release string does not end with a NUL byte.\n");
+ goto out;
+ }
+
+ /* Ensure inner block sizes are multiple of 64. */
+ if ((h.authentication_data_block_size & 0x3f) != 0 ||
+ (h.auxiliary_data_block_size & 0x3f) != 0) {
+ avb_error("Block size is not a multiple of 64.\n");
+ goto out;
+ }
+
+ /* Ensure block sizes all add up to at most |length|. */
+ uint64_t block_total = sizeof(AvbVBMetaImageHeader);
+ if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
+ !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
+ avb_error("Overflow while computing size of boot image.\n");
+ goto out;
+ }
+ if (block_total > length) {
+ avb_error("Block sizes add up to more than given length.\n");
+ goto out;
+ }
+
+ uintptr_t data_ptr = (uintptr_t)data;
+ /* Ensure passed in memory doesn't wrap. */
+ if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
+ avb_error("Boot image location and length mismatch.\n");
+ goto out;
+ }
+
+ /* Ensure hash and signature are entirely in the Authentication data block. */
+ uint64_t hash_end;
+ if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
+ hash_end > h.authentication_data_block_size) {
+ avb_error("Hash is not entirely in its block.\n");
+ goto out;
+ }
+ uint64_t signature_end;
+ if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
+ signature_end > h.authentication_data_block_size) {
+ avb_error("Signature is not entirely in its block.\n");
+ goto out;
+ }
+
+ /* Ensure public key is entirely in the Auxiliary data block. */
+ uint64_t pubkey_end;
+ if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
+ pubkey_end > h.auxiliary_data_block_size) {
+ avb_error("Public key is not entirely in its block.\n");
+ goto out;
+ }
+
+ /* Ensure public key metadata (if set) is entirely in the Auxiliary
+ * data block. */
+ if (h.public_key_metadata_size > 0) {
+ uint64_t pubkey_md_end;
+ if (!avb_safe_add(&pubkey_md_end,
+ h.public_key_metadata_offset,
+ h.public_key_metadata_size) ||
+ pubkey_md_end > h.auxiliary_data_block_size) {
+ avb_error("Public key metadata is not entirely in its block.\n");
+ goto out;
+ }
+ }
+
+ /* Bail early if there's no hash or signature. */
+ if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
+ ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
+ goto out;
+ }
+
+ /* Ensure algorithm field is supported. */
+ algorithm = avb_get_algorithm_data(h.algorithm_type);
+ if (!algorithm) {
+ avb_error("Invalid or unknown algorithm.\n");
+ goto out;
+ }
+
+ /* Bail if the embedded hash size doesn't match the chosen algorithm. */
+ if (h.hash_size != algorithm->hash_len) {
+ avb_error("Embedded hash has wrong size.\n");
+ goto out;
+ }
+
+ /* No overflow checks needed from here-on after since all block
+ * sizes and offsets have been verified above.
+ */
+
+ header_block = data;
+ authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
+ auxiliary_block = authentication_block + h.authentication_data_block_size;
+
+ switch (h.algorithm_type) {
+ /* Explicit fall-through: */
+ case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
+ avb_sha256_init(&sha256_ctx);
+ avb_sha256_update(
+ &sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
+ avb_sha256_update(
+ &sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
+ computed_hash = avb_sha256_final(&sha256_ctx);
+ break;
+ /* Explicit fall-through: */
+ case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
+ case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
+ avb_sha512_init(&sha512_ctx);
+ avb_sha512_update(
+ &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
+ avb_sha512_update(
+ &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
+ computed_hash = avb_sha512_final(&sha512_ctx);
+ break;
+ default:
+ avb_error("Unknown algorithm.\n");
+ goto out;
+ }
+
+ if (avb_safe_memcmp(authentication_block + h.hash_offset,
+ computed_hash,
+ h.hash_size) != 0) {
+ avb_error("Hash does not match!\n");
+ ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
+ goto out;
+ }
+
+ verification_result =
+ avb_rsa_verify(auxiliary_block + h.public_key_offset,
+ h.public_key_size,
+ authentication_block + h.signature_offset,
+ h.signature_size,
+ authentication_block + h.hash_offset,
+ h.hash_size,
+ algorithm->padding,
+ algorithm->padding_len);
+
+ if (verification_result == 0) {
+ ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
+ goto out;
+ }
+
+ if (h.public_key_size > 0) {
+ if (out_public_key_data != NULL) {
+ *out_public_key_data = auxiliary_block + h.public_key_offset;
+ }
+ if (out_public_key_length != NULL) {
+ *out_public_key_length = h.public_key_size;
+ }
+ }
+
+ ret = AVB_VBMETA_VERIFY_RESULT_OK;
+
+out:
+ return ret;
+}
+
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+ AvbVBMetaImageHeader* dest) {
+ avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
+
+ dest->required_libavb_version_major =
+ avb_be32toh(dest->required_libavb_version_major);
+ dest->required_libavb_version_minor =
+ avb_be32toh(dest->required_libavb_version_minor);
+
+ dest->authentication_data_block_size =
+ avb_be64toh(dest->authentication_data_block_size);
+ dest->auxiliary_data_block_size =
+ avb_be64toh(dest->auxiliary_data_block_size);
+
+ dest->algorithm_type = avb_be32toh(dest->algorithm_type);
+
+ dest->hash_offset = avb_be64toh(dest->hash_offset);
+ dest->hash_size = avb_be64toh(dest->hash_size);
+
+ dest->signature_offset = avb_be64toh(dest->signature_offset);
+ dest->signature_size = avb_be64toh(dest->signature_size);
+
+ dest->public_key_offset = avb_be64toh(dest->public_key_offset);
+ dest->public_key_size = avb_be64toh(dest->public_key_size);
+
+ dest->public_key_metadata_offset =
+ avb_be64toh(dest->public_key_metadata_offset);
+ dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
+
+ dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
+ dest->descriptors_size = avb_be64toh(dest->descriptors_size);
+
+ dest->rollback_index = avb_be64toh(dest->rollback_index);
+ dest->flags = avb_be32toh(dest->flags);
+}
+
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_VBMETA_VERIFY_RESULT_OK:
+ ret = "OK";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
+ ret = "OK_NOT_SIGNED";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
+ ret = "INVALID_VBMETA_HEADER";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
+ ret = "UNSUPPORTED_VERSION";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
+ ret = "HASH_MISMATCH";
+ break;
+ case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
+ ret = "SIGNATURE_MISMATCH";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbVBMetaVerifyResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}
diff --git a/lib/libavb/avb_vbmeta_image.h b/lib/libavb/avb_vbmeta_image.h
new file mode 100644
index 00000000..24f8519f
--- /dev/null
+++ b/lib/libavb/avb_vbmeta_image.h
@@ -0,0 +1,275 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VBMETA_IMAGE_H_
+#define AVB_VBMETA_IMAGE_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+
+/* Size of the vbmeta image header. */
+#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
+
+/* Magic for the vbmeta image header. */
+#define AVB_MAGIC "AVB0"
+#define AVB_MAGIC_LEN 4
+
+/* Maximum size of the release string including the terminating NUL byte. */
+#define AVB_RELEASE_STRING_SIZE 48
+
+/* Flags for the vbmeta image.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
+ * hashtree image verification will be disabled.
+ *
+ * AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
+ * verification will be disabled and descriptors will not be parsed.
+ */
+typedef enum {
+ AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
+ AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
+} AvbVBMetaImageFlags;
+
+/* Binary format for header of the vbmeta image.
+ *
+ * The vbmeta image consists of three blocks:
+ *
+ * +-----------------------------------------+
+ * | Header data - fixed size |
+ * +-----------------------------------------+
+ * | Authentication data - variable size |
+ * +-----------------------------------------+
+ * | Auxiliary data - variable size |
+ * +-----------------------------------------+
+ *
+ * The "Header data" block is described by this struct and is always
+ * |AVB_VBMETA_IMAGE_HEADER_SIZE| bytes long.
+ *
+ * The "Authentication data" block is |authentication_data_block_size|
+ * bytes long and contains the hash and signature used to authenticate
+ * the vbmeta image. The type of the hash and signature is defined by
+ * the |algorithm_type| field.
+ *
+ * The "Auxiliary data" is |auxiliary_data_block_size| bytes long and
+ * contains the auxiliary data including the public key used to make
+ * the signature and descriptors.
+ *
+ * The public key is at offset |public_key_offset| with size
+ * |public_key_size| in this block. The size of the public key data is
+ * defined by the |algorithm_type| field. The format of the public key
+ * data is described in the |AvbRSAPublicKeyHeader| struct.
+ *
+ * The descriptors starts at |descriptors_offset| from the beginning
+ * of the "Auxiliary Data" block and take up |descriptors_size|
+ * bytes. Each descriptor is stored as a |AvbDescriptor| with tag and
+ * number of bytes following. The number of descriptors can be
+ * determined by walking this data until |descriptors_size| is
+ * exhausted.
+ *
+ * The size of each of the "Authentication data" and "Auxiliary data"
+ * blocks must be divisible by 64. This is to ensure proper alignment.
+ *
+ * Descriptors are free-form blocks stored in a part of the vbmeta
+ * image subject to the same integrity checks as the rest of the
+ * image. See the documentation for |AvbDescriptor| for well-known
+ * descriptors. See avb_descriptor_foreach() for a convenience
+ * function to iterate over descriptors.
+ *
+ * This struct is versioned, see the |required_libavb_version_major|
+ * and |required_libavb_version_minor| fields. This represents the
+ * minimum version of libavb required to verify the header and depends
+ * on the features (e.g. algorithms, descriptors) used. Note that this
+ * may be 1.0 even if generated by an avbtool from 1.4 but where no
+ * features introduced after 1.0 has been used. See the "Versioning
+ * and compatibility" section in the README.md file for more details.
+ *
+ * All fields are stored in network byte order when serialized. To
+ * generate a copy with fields swapped to native byte order, use the
+ * function avb_vbmeta_image_header_to_host_byte_order().
+ *
+ * Before reading and/or using any of this data, you MUST verify it
+ * using avb_vbmeta_image_verify() and reject it unless it's signed by
+ * a known good public key.
+ */
+typedef struct AvbVBMetaImageHeader {
+ /* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
+ uint8_t magic[AVB_MAGIC_LEN];
+
+ /* 4: The major version of libavb required for this header. */
+ uint32_t required_libavb_version_major;
+ /* 8: The minor version of libavb required for this header. */
+ uint32_t required_libavb_version_minor;
+
+ /* 12: The size of the signature block. */
+ uint64_t authentication_data_block_size;
+ /* 20: The size of the auxiliary data block. */
+ uint64_t auxiliary_data_block_size;
+
+ /* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
+ uint32_t algorithm_type;
+
+ /* 32: Offset into the "Authentication data" block of hash data. */
+ uint64_t hash_offset;
+ /* 40: Length of the hash data. */
+ uint64_t hash_size;
+
+ /* 48: Offset into the "Authentication data" block of signature data. */
+ uint64_t signature_offset;
+ /* 56: Length of the signature data. */
+ uint64_t signature_size;
+
+ /* 64: Offset into the "Auxiliary data" block of public key data. */
+ uint64_t public_key_offset;
+ /* 72: Length of the public key data. */
+ uint64_t public_key_size;
+
+ /* 80: Offset into the "Auxiliary data" block of public key metadata. */
+ uint64_t public_key_metadata_offset;
+ /* 88: Length of the public key metadata. Must be set to zero if there
+ * is no public key metadata.
+ */
+ uint64_t public_key_metadata_size;
+
+ /* 96: Offset into the "Auxiliary data" block of descriptor data. */
+ uint64_t descriptors_offset;
+ /* 104: Length of descriptor data. */
+ uint64_t descriptors_size;
+
+ /* 112: The rollback index which can be used to prevent rollback to
+ * older versions.
+ */
+ uint64_t rollback_index;
+
+ /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
+ * set to zero if the vbmeta image is not a top-level image.
+ */
+ uint32_t flags;
+
+ /* 124: Reserved to ensure |release_string| start on a 16-byte
+ * boundary. Must be set to zeroes.
+ */
+ uint8_t reserved0[4];
+
+ /* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
+ * "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
+ * terminated. Applications must not make assumptions about how this
+ * string is formatted.
+ */
+ uint8_t release_string[AVB_RELEASE_STRING_SIZE];
+
+ /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
+ * bytes. This must be set to zeroes.
+ */
+ uint8_t reserved[80];
+} AVB_ATTR_PACKED AvbVBMetaImageHeader;
+
+/* Copies |src| to |dest|, byte-swapping fields in the process.
+ *
+ * Make sure you've verified |src| using avb_vbmeta_image_verify()
+ * before accessing the data and/or using this function.
+ */
+void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
+ AvbVBMetaImageHeader* dest);
+
+/* Return codes used in avb_vbmeta_image_verify().
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK is returned if the vbmeta image header
+ * is valid, the hash is correct and the signature is correct. Keep in
+ * mind that you still need to check that you know the public key used
+ * to sign the image, see avb_vbmeta_image_verify() for details.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED is returned if the vbmeta
+ * image header is valid but there is no signature or hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER is returned if the
+ * header of the vbmeta image is invalid, for example, invalid magic
+ * or inconsistent data.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION is returned if a) the
+ * vbmeta image requires a minimum version of libavb which exceeds the
+ * version of libavb used; or b) the vbmeta image major version
+ * differs from the major version of libavb in use.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH is returned if the hash
+ * stored in the "Authentication data" block does not match the
+ * calculated hash.
+ *
+ * AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH is returned if the
+ * signature stored in the "Authentication data" block is invalid or
+ * doesn't match the public key stored in the vbmeta image.
+ */
+typedef enum {
+ AVB_VBMETA_VERIFY_RESULT_OK,
+ AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
+ AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
+ AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
+ AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
+ AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
+} AvbVBMetaVerifyResult;
+
+/* Get a textual representation of |result|. */
+const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result);
+
+/* Checks that vbmeta image at |data| of size |length| is a valid
+ * vbmeta image. The complete contents of the vbmeta image must be
+ * passed in. It's fine if |length| is bigger than the actual image,
+ * typically callers of this function will load the entire contents of
+ * the 'vbmeta_a' or 'vbmeta_b' partition and pass in its length (for
+ * example, 1 MiB).
+ *
+ * See the |AvbVBMetaImageHeader| struct for information about the
+ * three blocks (header, authentication, auxiliary) that make up a
+ * vbmeta image.
+ *
+ * If the function returns |AVB_VBMETA_VERIFY_RESULT_OK| and
+ * |out_public_key_data| is non-NULL, it will be set to point inside
+ * |data| for where the serialized public key data is stored and
+ * |out_public_key_length|, if non-NULL, will be set to the length of
+ * the public key data. If there is no public key in the metadata then
+ * |out_public_key_data| is set to NULL.
+ *
+ * See the |AvbVBMetaVerifyResult| enum for possible return values.
+ *
+ * VERY IMPORTANT:
+ *
+ * 1. Even if |AVB_VBMETA_VERIFY_RESULT_OK| is returned, you still
+ * need to check that the public key embedded in the image
+ * matches a known key! You can use 'avbtool extract_public_key'
+ * to extract the key (at build time, then store it along your
+ * code) and compare it to what is returned in
+ * |out_public_key_data|.
+ *
+ * 2. You need to check the |rollback_index| field against a stored
+ * value in NVRAM and reject the vbmeta image if the value in
+ * NVRAM is bigger than |rollback_index|. You must also update
+ * the value stored in NVRAM to the smallest value of
+ * |rollback_index| field from boot images in all bootable and
+ * authentic slots marked as GOOD.
+ *
+ * This is a low-level function to only verify the vbmeta data - you
+ * are likely looking for avb_slot_verify() instead for verifying
+ * integrity data for a whole set of partitions.
+ */
+AvbVBMetaVerifyResult avb_vbmeta_image_verify(
+ const uint8_t* data,
+ size_t length,
+ const uint8_t** out_public_key_data,
+ size_t* out_public_key_length) AVB_ATTR_WARN_UNUSED_RESULT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VBMETA_IMAGE_H_ */
diff --git a/lib/libavb/avb_version.c b/lib/libavb/avb_version.c
new file mode 100644
index 00000000..1f20722e
--- /dev/null
+++ b/lib/libavb/avb_version.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+
+#include "avb_version.h"
+
+#define AVB_QUOTE(str) #str
+#define AVB_EXPAND_AND_QUOTE(str) AVB_QUOTE(str)
+
+/* Keep in sync with get_release_string() in avbtool. */
+const char* avb_version_string(void) {
+ return AVB_EXPAND_AND_QUOTE(AVB_VERSION_MAJOR) "." AVB_EXPAND_AND_QUOTE(
+ AVB_VERSION_MINOR) "." AVB_EXPAND_AND_QUOTE(AVB_VERSION_SUB);
+}
diff --git a/lib/libavb/avb_version.h b/lib/libavb/avb_version.h
new file mode 100644
index 00000000..57c6ece8
--- /dev/null
+++ b/lib/libavb/avb_version.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+
+#if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION)
+#error "Never include this file directly, include libavb.h instead."
+#endif
+
+#ifndef AVB_VERSION_H_
+#define AVB_VERSION_H_
+
+#include "avb_sysdeps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The version number of AVB - keep in sync with avbtool. */
+#define AVB_VERSION_MAJOR 1
+#define AVB_VERSION_MINOR 1
+#define AVB_VERSION_SUB 0
+
+/* Returns a NUL-terminated string for the libavb version in use. The
+ * returned string usually looks like "%d.%d.%d". Applications must
+ * not make assumptions about the content of this string.
+ *
+ * Boot loaders should display this string in debug/diagnostics output
+ * to aid with debugging.
+ *
+ * This is similar to the string put in the |release_string| string
+ * field in the VBMeta struct by avbtool.
+ */
+const char* avb_version_string(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AVB_VERSION_H_ */
diff --git a/lib/libavb/libavb.h b/lib/libavb/libavb.h
new file mode 100644
index 00000000..ac92a2bc
--- /dev/null
+++ b/lib/libavb/libavb.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ */
+
+#ifndef LIBAVB_H_
+#define LIBAVB_H_
+
+/* The AVB_INSIDE_LIBAVB_H preprocessor symbol is used to enforce
+ * library users to include only this file. All public interfaces, and
+ * only public interfaces, must be included here.
+ */
+
+#define AVB_INSIDE_LIBAVB_H
+#include "avb_chain_partition_descriptor.h"
+#include "avb_crypto.h"
+#include "avb_descriptor.h"
+#include "avb_footer.h"
+#include "avb_hash_descriptor.h"
+#include "avb_hashtree_descriptor.h"
+#include "avb_kernel_cmdline_descriptor.h"
+#include "avb_ops.h"
+#include "avb_property_descriptor.h"
+#include "avb_slot_verify.h"
+#include "avb_sysdeps.h"
+#include "avb_util.h"
+#include "avb_vbmeta_image.h"
+#include "avb_version.h"
+#undef AVB_INSIDE_LIBAVB_H
+
+#endif /* LIBAVB_H_ */
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
new file mode 100644
index 00000000..5d3ae4e2
--- /dev/null
+++ b/lib/libfdt/Makefile
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+# Use upstream code.
+obj-y += \
+ fdt.o \
+ fdt_wip.o \
+ fdt_strerror.o \
+ fdt_sw.o \
+ fdt_rw.o \
+ fdt_empty_tree.o \
+ fdt_addresses.o
+
+obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
+
+# Locally modified for U-Boot.
+# TODO: split out the local modifiction.
+obj-y += fdt_ro.o
+
+# U-Boot own file
+obj-y += fdt_region.o
+
+ccflags-y := -I$(srctree)/scripts/dtc/libfdt \
+ -DFDT_ASSUME_MASK=$(CONFIG_$(SPL_TPL_)OF_LIBFDT_ASSUME_MASK)
diff --git a/lib/libfdt/README b/lib/libfdt/README
new file mode 100644
index 00000000..db40ab25
--- /dev/null
+++ b/lib/libfdt/README
@@ -0,0 +1,25 @@
+The libfdt functionality was written by David Gibson. The original
+source came from the Git repository:
+
+URL: git://ozlabs.org/home/dgibson/git/libfdt.git
+
+author David Gibson <dgibson@sneetch.(none)>
+ Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100)
+committer David Gibson <dgibson@sneetch.(none)>
+ Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100)
+commit 857f54e79f74429af20c2b5ecc00ee98af6a3b8b
+tree 2f648f0f88225a51ded452968d28b4402df8ade0
+parent 07a12a08005f3b5cd9337900a6551e450c07b515
+
+To adapt for U-Boot usage, only the applicable files were copied and
+imported into the U-Boot Git repository.
+
+Omitted:
+
+ * GPL - U-Boot comes with a copy of the GPL license
+ * test subdirectory - not directly useful for U-Boot
+
+After importing, other customizations were performed. See the
+"git log" for details.
+
+Jerry Van Baren
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
new file mode 100644
index 00000000..0958e6ba
--- /dev/null
+++ b/lib/libfdt/fdt.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt.c"
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
new file mode 100644
index 00000000..b82a0293
--- /dev/null
+++ b/lib/libfdt/fdt_addresses.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_addresses.c"
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
new file mode 100644
index 00000000..2b4ae106
--- /dev/null
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_empty_tree.c"
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
new file mode 100644
index 00000000..575c8276
--- /dev/null
+++ b/lib/libfdt/fdt_overlay.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_overlay.c"
diff --git a/lib/libfdt/fdt_region.c b/lib/libfdt/fdt_region.c
new file mode 100644
index 00000000..7e9fa927
--- /dev/null
+++ b/lib/libfdt/fdt_region.c
@@ -0,0 +1,656 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2013 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <linux/libfdt_env.h>
+
+#ifndef USE_HOSTCC
+#include <fdt.h>
+#include <linux/libfdt.h>
+#else
+#include "fdt_host.h"
+#endif
+
+#define FDT_MAX_DEPTH 32
+
+static int str_in_list(const char *str, char * const list[], int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ if (!strcmp(list[i], str))
+ return 1;
+
+ return 0;
+}
+
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+ char * const exc_prop[], int exc_prop_count,
+ struct fdt_region region[], int max_regions,
+ char *path, int path_len, int add_string_tab)
+{
+ int stack[FDT_MAX_DEPTH] = { 0 };
+ char *end;
+ int nextoffset = 0;
+ uint32_t tag;
+ int count = 0;
+ int start = -1;
+ int depth = -1;
+ int want = 0;
+ int base = fdt_off_dt_struct(fdt);
+
+ end = path;
+ *end = '\0';
+ do {
+ const struct fdt_property *prop;
+ const char *name;
+ const char *str;
+ int include = 0;
+ int stop_at = 0;
+ int offset;
+ int len;
+
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ stop_at = nextoffset;
+
+ switch (tag) {
+ case FDT_PROP:
+ include = want >= 2;
+ stop_at = offset;
+ prop = fdt_get_property_by_offset(fdt, offset, NULL);
+ str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ if (str_in_list(str, exc_prop, exc_prop_count))
+ include = 0;
+ break;
+
+ case FDT_NOP:
+ include = want >= 2;
+ stop_at = offset;
+ break;
+
+ case FDT_BEGIN_NODE:
+ depth++;
+ if (depth == FDT_MAX_DEPTH)
+ return -FDT_ERR_BADSTRUCTURE;
+ name = fdt_get_name(fdt, offset, &len);
+ if (end - path + 2 + len >= path_len)
+ return -FDT_ERR_NOSPACE;
+ if (end != path + 1)
+ *end++ = '/';
+ strcpy(end, name);
+ end += len;
+ stack[depth] = want;
+ if (want == 1)
+ stop_at = offset;
+ if (str_in_list(path, inc, inc_count))
+ want = 2;
+ else if (want)
+ want--;
+ else
+ stop_at = offset;
+ include = want;
+ break;
+
+ case FDT_END_NODE:
+ /* Depth must never go below -1 */
+ if (depth < 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ include = want;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+ *end = '\0';
+ break;
+
+ case FDT_END:
+ include = 1;
+ break;
+ }
+
+ if (include && start == -1) {
+ /* Should we merge with previous? */
+ if (count && count <= max_regions &&
+ offset == region[count - 1].offset +
+ region[count - 1].size - base)
+ start = region[--count].offset - base;
+ else
+ start = offset;
+ }
+
+ if (!include && start != -1) {
+ if (count < max_regions) {
+ region[count].offset = base + start;
+ region[count].size = stop_at - start;
+ }
+ count++;
+ start = -1;
+ }
+ } while (tag != FDT_END);
+
+ if (nextoffset != fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADLAYOUT;
+
+ /* Add a region for the END tag and the string table */
+ if (count < max_regions) {
+ region[count].offset = base + start;
+ region[count].size = nextoffset - start;
+ if (add_string_tab)
+ region[count].size += fdt_size_dt_strings(fdt);
+ }
+ count++;
+
+ return count;
+}
+
+/**
+ * fdt_add_region() - Add a new region to our list
+ * @info: State information
+ * @offset: Start offset of region
+ * @size: Size of region
+ *
+ * The region is added if there is space, but in any case we increment the
+ * count. If permitted, and the new region overlaps the last one, we merge
+ * them.
+ */
+static int fdt_add_region(struct fdt_region_state *info, int offset, int size)
+{
+ struct fdt_region *reg;
+
+ reg = info->region ? &info->region[info->count - 1] : NULL;
+ if (info->can_merge && info->count &&
+ info->count <= info->max_regions &&
+ reg && offset <= reg->offset + reg->size) {
+ reg->size = offset + size - reg->offset;
+ } else if (info->count++ < info->max_regions) {
+ if (reg) {
+ reg++;
+ reg->offset = offset;
+ reg->size = size;
+ }
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int region_list_contains_offset(struct fdt_region_state *info,
+ const void *fdt, int target)
+{
+ struct fdt_region *reg;
+ int num;
+
+ target += fdt_off_dt_struct(fdt);
+ for (reg = info->region, num = 0; num < info->count; reg++, num++) {
+ if (target >= reg->offset && target < reg->offset + reg->size)
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * fdt_add_alias_regions() - Add regions covering the aliases that we want
+ *
+ * The /aliases node is not automatically included by fdtgrep unless the
+ * command-line arguments cause to be included (or not excluded). However
+ * aliases are special in that we generally want to include those which
+ * reference a node that fdtgrep includes.
+ *
+ * In fact we want to include only aliases for those nodes still included in
+ * the fdt, and drop the other aliases since they point to nodes that will not
+ * be present.
+ *
+ * This function scans the aliases and adds regions for those which we want
+ * to keep.
+ *
+ * @fdt: Device tree to scan
+ * @region: List of regions
+ * @count: Number of regions in the list so far (i.e. starting point for this
+ * function)
+ * @max_regions: Maximum number of regions in @region list
+ * @info: Place to put the region state
+ * @return number of regions after processing, or -FDT_ERR_NOSPACE if we did
+ * not have enough room in the regions table for the regions we wanted to add.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+ int max_regions, struct fdt_region_state *info)
+{
+ int base = fdt_off_dt_struct(fdt);
+ int node, node_end, offset;
+ int did_alias_header;
+
+ node = fdt_subnode_offset(fdt, 0, "aliases");
+ if (node < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ /*
+ * Find the next node so that we know where the /aliases node ends. We
+ * need special handling if /aliases is the last node.
+ */
+ node_end = fdt_next_subnode(fdt, node);
+ if (node_end == -FDT_ERR_NOTFOUND)
+ /* Move back to the FDT_END_NODE tag of '/' */
+ node_end = fdt_size_dt_struct(fdt) - sizeof(fdt32_t) * 2;
+ else if (node_end < 0) /* other error */
+ return node_end;
+ node_end -= sizeof(fdt32_t); /* Move to FDT_END_NODE tag of /aliases */
+
+ did_alias_header = 0;
+ info->region = region;
+ info->count = count;
+ info->can_merge = 0;
+ info->max_regions = max_regions;
+
+ for (offset = fdt_first_property_offset(fdt, node);
+ offset >= 0;
+ offset = fdt_next_property_offset(fdt, offset)) {
+ const struct fdt_property *prop;
+ const char *name;
+ int target, next;
+
+ prop = fdt_get_property_by_offset(fdt, offset, NULL);
+ name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ target = fdt_path_offset(fdt, name);
+ if (!region_list_contains_offset(info, fdt, target))
+ continue;
+ next = fdt_next_property_offset(fdt, offset);
+ if (next < 0)
+ next = node_end;
+
+ if (!did_alias_header) {
+ fdt_add_region(info, base + node, 12);
+ did_alias_header = 1;
+ }
+ fdt_add_region(info, base + offset, next - offset);
+ }
+
+ /* Add the FDT_END_NODE tag */
+ if (did_alias_header)
+ fdt_add_region(info, base + node_end, sizeof(fdt32_t));
+
+ return info->count < max_regions ? info->count : -FDT_ERR_NOSPACE;
+}
+
+/**
+ * fdt_include_supernodes() - Include supernodes required by this node
+ * @info: State information
+ * @depth: Current stack depth
+ *
+ * When we decided to include a node or property which is not at the top
+ * level, this function forces the inclusion of higher level nodes. For
+ * example, given this tree:
+ *
+ * / {
+ * testing {
+ * }
+ * }
+ *
+ * If we decide to include testing then we need the root node to have a valid
+ * tree. This function adds those regions.
+ */
+static int fdt_include_supernodes(struct fdt_region_state *info, int depth)
+{
+ int base = fdt_off_dt_struct(info->fdt);
+ int start, stop_at;
+ int i;
+
+ /*
+ * Work down the stack looking for supernodes that we didn't include.
+ * The algortihm here is actually pretty simple, since we know that
+ * no previous subnode had to include these nodes, or if it did, we
+ * marked them as included (on the stack) already.
+ */
+ for (i = 0; i <= depth; i++) {
+ if (!info->stack[i].included) {
+ start = info->stack[i].offset;
+
+ /* Add the FDT_BEGIN_NODE tag of this supernode */
+ fdt_next_tag(info->fdt, start, &stop_at);
+ if (fdt_add_region(info, base + start, stop_at - start))
+ return -1;
+
+ /* Remember that this supernode is now included */
+ info->stack[i].included = 1;
+ info->can_merge = 1;
+ }
+
+ /* Force (later) generation of the FDT_END_NODE tag */
+ if (!info->stack[i].want)
+ info->stack[i].want = WANT_NODES_ONLY;
+ }
+
+ return 0;
+}
+
+enum {
+ FDT_DONE_NOTHING,
+ FDT_DONE_MEM_RSVMAP,
+ FDT_DONE_STRUCT,
+ FDT_DONE_END,
+ FDT_DONE_STRINGS,
+ FDT_DONE_ALL,
+};
+
+int fdt_first_region(const void *fdt,
+ int (*h_include)(void *priv, const void *fdt, int offset,
+ int type, const char *data, int size),
+ void *priv, struct fdt_region *region,
+ char *path, int path_len, int flags,
+ struct fdt_region_state *info)
+{
+ struct fdt_region_ptrs *p = &info->ptrs;
+
+ /* Set up our state */
+ info->fdt = fdt;
+ info->can_merge = 1;
+ info->max_regions = 1;
+ info->start = -1;
+ p->want = WANT_NOTHING;
+ p->end = path;
+ *p->end = '\0';
+ p->nextoffset = 0;
+ p->depth = -1;
+ p->done = FDT_DONE_NOTHING;
+
+ return fdt_next_region(fdt, h_include, priv, region,
+ path, path_len, flags, info);
+}
+
+/***********************************************************************
+ *
+ * Theory of operation
+ *
+ * Note: in this description 'included' means that a node (or other part
+ * of the tree) should be included in the region list, i.e. it will have
+ * a region which covers its part of the tree.
+ *
+ * This function maintains some state from the last time it is called.
+ * It checks the next part of the tree that it is supposed to look at
+ * (p.nextoffset) to see if that should be included or not. When it
+ * finds something to include, it sets info->start to its offset. This
+ * marks the start of the region we want to include.
+ *
+ * Once info->start is set to the start (i.e. not -1), we continue
+ * scanning until we find something that we don't want included. This
+ * will be the end of a region. At this point we can close off the
+ * region and add it to the list. So we do so, and reset info->start
+ * to -1.
+ *
+ * One complication here is that we want to merge regions. So when we
+ * come to add another region later, we may in fact merge it with the
+ * previous one if one ends where the other starts.
+ *
+ * The function fdt_add_region() will return -1 if it fails to add the
+ * region, because we already have a region ready to be returned, and
+ * the new one cannot be merged in with it. In this case, we must return
+ * the region we found, and wait for another call to this function.
+ * When it comes, we will repeat the processing of the tag and again
+ * try to add a region. This time it will succeed.
+ *
+ * The current state of the pointers (stack, offset, etc.) is maintained
+ * in a ptrs member. At the start of every loop iteration we make a copy
+ * of it. The copy is then updated as the tag is processed. Only if we
+ * get to the end of the loop iteration (and successfully call
+ * fdt_add_region() if we need to) can we commit the changes we have
+ * made to these pointers. For example, if we see an FDT_END_NODE tag,
+ * we will decrement the depth value. But if we need to add a region
+ * for this tag (let's say because the previous tag is included and this
+ * FDT_END_NODE tag is not included) then we will only commit the result
+ * if we were able to add the region. That allows us to retry again next
+ * time.
+ *
+ * We keep track of a variable called 'want' which tells us what we want
+ * to include when there is no specific information provided by the
+ * h_include function for a particular property. This basically handles
+ * the inclusion of properties which are pulled in by virtue of the node
+ * they are in. So if you include a node, its properties are also
+ * included. In this case 'want' will be WANT_NODES_AND_PROPS. The
+ * FDT_REG_DIRECT_SUBNODES feature also makes use of 'want'. While we
+ * are inside the subnode, 'want' will be set to WANT_NODES_ONLY, so
+ * that only the subnode's FDT_BEGIN_NODE and FDT_END_NODE tags will be
+ * included, and properties will be skipped. If WANT_NOTHING is
+ * selected, then we will just rely on what the h_include() function
+ * tells us.
+ *
+ * Using 'want' we work out 'include', which tells us whether this
+ * current tag should be included or not. As you can imagine, if the
+ * value of 'include' changes, that means we are on a boundary between
+ * nodes to include and nodes to exclude. At this point we either close
+ * off a previous region and add it to the list, or mark the start of a
+ * new region.
+ *
+ * Apart from the nodes, we have mem_rsvmap, the FDT_END tag and the
+ * string list. Each of these dealt with as a whole (i.e. we create a
+ * region for each if it is to be included). For mem_rsvmap we don't
+ * allow it to merge with the first struct region. For the stringlist,
+ * we don't allow it to merge with the last struct region (which
+ * contains at minimum the FDT_END tag).
+ *
+ *********************************************************************/
+
+int fdt_next_region(const void *fdt,
+ int (*h_include)(void *priv, const void *fdt, int offset,
+ int type, const char *data, int size),
+ void *priv, struct fdt_region *region,
+ char *path, int path_len, int flags,
+ struct fdt_region_state *info)
+{
+ int base = fdt_off_dt_struct(fdt);
+ int last_node = 0;
+ const char *str;
+
+ info->region = region;
+ info->count = 0;
+ if (info->ptrs.done < FDT_DONE_MEM_RSVMAP &&
+ (flags & FDT_REG_ADD_MEM_RSVMAP)) {
+ /* Add the memory reserve map into its own region */
+ if (fdt_add_region(info, fdt_off_mem_rsvmap(fdt),
+ fdt_off_dt_struct(fdt) -
+ fdt_off_mem_rsvmap(fdt)))
+ return 0;
+ info->can_merge = 0; /* Don't allow merging with this */
+ info->ptrs.done = FDT_DONE_MEM_RSVMAP;
+ }
+
+ /*
+ * Work through the tags one by one, deciding whether each needs to
+ * be included or not. We set the variable 'include' to indicate our
+ * decision. 'want' is used to track what we want to include - it
+ * allows us to pick up all the properties (and/or subnode tags) of
+ * a node.
+ */
+ while (info->ptrs.done < FDT_DONE_STRUCT) {
+ const struct fdt_property *prop;
+ struct fdt_region_ptrs p;
+ const char *name;
+ int include = 0;
+ int stop_at = 0;
+ uint32_t tag;
+ int offset;
+ int val;
+ int len;
+
+ /*
+ * Make a copy of our pointers. If we make it to the end of
+ * this block then we will commit them back to info->ptrs.
+ * Otherwise we can try again from the same starting state
+ * next time we are called.
+ */
+ p = info->ptrs;
+
+ /*
+ * Find the tag, and the offset of the next one. If we need to
+ * stop including tags, then by default we stop *after*
+ * including the current tag
+ */
+ offset = p.nextoffset;
+ tag = fdt_next_tag(fdt, offset, &p.nextoffset);
+ stop_at = p.nextoffset;
+
+ switch (tag) {
+ case FDT_PROP:
+ stop_at = offset;
+ prop = fdt_get_property_by_offset(fdt, offset, NULL);
+ str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ val = h_include(priv, fdt, last_node, FDT_IS_PROP, str,
+ strlen(str) + 1);
+ if (val == -1) {
+ include = p.want >= WANT_NODES_AND_PROPS;
+ } else {
+ include = val;
+ /*
+ * Make sure we include the } for this block.
+ * It might be more correct to have this done
+ * by the call to fdt_include_supernodes() in
+ * the case where it adds the node we are
+ * currently in, but this is equivalent.
+ */
+ if ((flags & FDT_REG_SUPERNODES) && val &&
+ !p.want)
+ p.want = WANT_NODES_ONLY;
+ }
+
+ /* Value grepping is not yet supported */
+ break;
+
+ case FDT_NOP:
+ include = p.want >= WANT_NODES_AND_PROPS;
+ stop_at = offset;
+ break;
+
+ case FDT_BEGIN_NODE:
+ last_node = offset;
+ p.depth++;
+ if (p.depth == FDT_MAX_DEPTH)
+ return -FDT_ERR_BADSTRUCTURE;
+ name = fdt_get_name(fdt, offset, &len);
+ if (p.end - path + 2 + len >= path_len)
+ return -FDT_ERR_NOSPACE;
+
+ /* Build the full path of this node */
+ if (p.end != path + 1)
+ *p.end++ = '/';
+ strcpy(p.end, name);
+ p.end += len;
+ info->stack[p.depth].want = p.want;
+ info->stack[p.depth].offset = offset;
+
+ /*
+ * If we are not intending to include this node unless
+ * it matches, make sure we stop *before* its tag.
+ */
+ if (p.want == WANT_NODES_ONLY ||
+ !(flags & (FDT_REG_DIRECT_SUBNODES |
+ FDT_REG_ALL_SUBNODES))) {
+ stop_at = offset;
+ p.want = WANT_NOTHING;
+ }
+ val = h_include(priv, fdt, offset, FDT_IS_NODE, path,
+ p.end - path + 1);
+
+ /* Include this if requested */
+ if (val) {
+ p.want = (flags & FDT_REG_ALL_SUBNODES) ?
+ WANT_ALL_NODES_AND_PROPS :
+ WANT_NODES_AND_PROPS;
+ }
+
+ /* If not requested, decay our 'p.want' value */
+ else if (p.want) {
+ if (p.want != WANT_ALL_NODES_AND_PROPS)
+ p.want--;
+
+ /* Not including this tag, so stop now */
+ } else {
+ stop_at = offset;
+ }
+
+ /*
+ * Decide whether to include this tag, and update our
+ * stack with the state for this node
+ */
+ include = p.want;
+ info->stack[p.depth].included = include;
+ break;
+
+ case FDT_END_NODE:
+ include = p.want;
+ if (p.depth < 0)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ /*
+ * If we don't want this node, stop right away, unless
+ * we are including subnodes
+ */
+ if (!p.want && !(flags & FDT_REG_DIRECT_SUBNODES))
+ stop_at = offset;
+ p.want = info->stack[p.depth].want;
+ p.depth--;
+ while (p.end > path && *--p.end != '/')
+ ;
+ *p.end = '\0';
+ break;
+
+ case FDT_END:
+ /* We always include the end tag */
+ include = 1;
+ p.done = FDT_DONE_STRUCT;
+ break;
+ }
+
+ /* If this tag is to be included, mark it as region start */
+ if (include && info->start == -1) {
+ /* Include any supernodes required by this one */
+ if (flags & FDT_REG_SUPERNODES) {
+ if (fdt_include_supernodes(info, p.depth))
+ return 0;
+ }
+ info->start = offset;
+ }
+
+ /*
+ * If this tag is not to be included, finish up the current
+ * region.
+ */
+ if (!include && info->start != -1) {
+ if (fdt_add_region(info, base + info->start,
+ stop_at - info->start))
+ return 0;
+ info->start = -1;
+ info->can_merge = 1;
+ }
+
+ /* If we have made it this far, we can commit our pointers */
+ info->ptrs = p;
+ }
+
+ /* Add a region for the END tag and a separate one for string table */
+ if (info->ptrs.done < FDT_DONE_END) {
+ if (info->ptrs.nextoffset != fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADSTRUCTURE;
+
+ if (fdt_add_region(info, base + info->start,
+ info->ptrs.nextoffset - info->start))
+ return 0;
+ info->ptrs.done++;
+ }
+ if (info->ptrs.done < FDT_DONE_STRINGS) {
+ if (flags & FDT_REG_ADD_STRING_TAB) {
+ info->can_merge = 0;
+ if (fdt_off_dt_strings(fdt) <
+ base + info->ptrs.nextoffset)
+ return -FDT_ERR_BADLAYOUT;
+ if (fdt_add_region(info, fdt_off_dt_strings(fdt),
+ fdt_size_dt_strings(fdt)))
+ return 0;
+ }
+ info->ptrs.done++;
+ }
+
+ return info->count > 0 ? 0 : -FDT_ERR_NOTFOUND;
+}
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
new file mode 100644
index 00000000..560041b6
--- /dev/null
+++ b/lib/libfdt/fdt_ro.c
@@ -0,0 +1,925 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <linux/libfdt_env.h>
+
+#ifndef USE_HOSTCC
+#include <fdt.h>
+#include <linux/libfdt.h>
+#else
+#include "fdt_host.h"
+#endif
+
+#include "libfdt_internal.h"
+
+static int fdt_nodename_eq_(const void *fdt, int offset,
+ const char *s, int len)
+{
+ int olen;
+ const char *p = fdt_get_name(fdt, offset, &olen);
+
+ if (!p || (fdt_chk_extra() && olen < len))
+ /* short match */
+ return 0;
+
+ if (memcmp(p, s, len) != 0)
+ return 0;
+
+ if (p[len] == '\0')
+ return 1;
+ else if (!memchr(s, '@', len) && (p[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+ int32_t totalsize;
+ uint32_t absoffset;
+ size_t len;
+ int err;
+ const char *s, *n;
+
+ if (!fdt_chk_extra()) {
+ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+ if (lenp)
+ *lenp = strlen(s);
+ return s;
+ }
+ totalsize = fdt_ro_probe_(fdt);
+ err = totalsize;
+ if (totalsize < 0)
+ goto fail;
+
+ err = -FDT_ERR_BADOFFSET;
+ absoffset = stroffset + fdt_off_dt_strings(fdt);
+ if (absoffset >= totalsize)
+ goto fail;
+ len = totalsize - absoffset;
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (stroffset < 0)
+ goto fail;
+ if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
+ if (stroffset >= fdt_size_dt_strings(fdt))
+ goto fail;
+ if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+ len = fdt_size_dt_strings(fdt) - stroffset;
+ }
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ if ((stroffset >= 0)
+ || (stroffset < -fdt_size_dt_strings(fdt)))
+ goto fail;
+ if ((-stroffset) < len)
+ len = -stroffset;
+ } else {
+ err = -FDT_ERR_INTERNAL;
+ goto fail;
+ }
+
+ s = (const char *)fdt + absoffset;
+ n = memchr(s, '\0', len);
+ if (!n) {
+ /* missing terminating NULL */
+ err = -FDT_ERR_TRUNCATED;
+ goto fail;
+ }
+
+ if (lenp)
+ *lenp = n - s;
+ return s;
+
+fail:
+ if (lenp)
+ *lenp = err;
+ return NULL;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+ return fdt_get_string(fdt, stroffset, NULL);
+}
+
+static int fdt_string_eq_(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ int slen;
+ const char *p = fdt_get_string(fdt, stroffset, &slen);
+
+ return p && (slen == len) && (memcmp(p, s, len) == 0);
+}
+
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
+{
+ uint32_t max = 0;
+ int offset = -1;
+
+ while (true) {
+ uint32_t value;
+
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
+
+ return offset;
+ }
+
+ value = fdt_get_phandle(fdt, offset);
+
+ if (value > max)
+ max = value;
+ }
+
+ if (phandle)
+ *phandle = max;
+
+ return 0;
+}
+
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+ uint32_t max;
+ int err;
+
+ err = fdt_find_max_phandle(fdt, &max);
+ if (err < 0)
+ return err;
+
+ if (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ return 0;
+}
+
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+ int offset = n * sizeof(struct fdt_reserve_entry);
+ int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+ if (fdt_chk_extra()) {
+ if (absoffset < fdt_off_mem_rsvmap(fdt))
+ return NULL;
+ if (absoffset > fdt_totalsize(fdt) -
+ sizeof(struct fdt_reserve_entry))
+ return NULL;
+ }
+ return fdt_mem_rsv_(fdt, n);
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+ const struct fdt_reserve_entry *re;
+
+ FDT_RO_PROBE(fdt);
+ re = fdt_mem_rsv(fdt, n);
+ if (fdt_chk_extra() && !re)
+ return -FDT_ERR_BADOFFSET;
+
+ *address = fdt64_ld(&re->address);
+ *size = fdt64_ld(&re->size);
+ return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+ int i;
+ const struct fdt_reserve_entry *re;
+
+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+ if (fdt64_ld(&re->size) == 0)
+ return i;
+ }
+ return -FDT_ERR_TRUNCATED;
+}
+
+static int nextprop_(const void *fdt, int offset)
+{
+ uint32_t tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+ const char *name, int namelen)
+{
+ int depth;
+
+ FDT_RO_PROBE(fdt);
+
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && fdt_nodename_eq_(fdt, offset, name, namelen))
+ return offset;
+
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+ const char *name)
+{
+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
+{
+ const char *end = path + namelen;
+ const char *p = path;
+ int offset = 0;
+
+ FDT_RO_PROBE(fdt);
+
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = memchr(path, '/', end - p);
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
+
+ while (p < end) {
+ const char *q;
+
+ while (*p == '/') {
+ p++;
+ if (p == end)
+ return offset;
+ }
+ q = memchr(p, '/', end - p);
+ if (! q)
+ q = end;
+
+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+ if (offset < 0)
+ return offset;
+
+ p = q;
+ }
+
+ return offset;
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ return fdt_path_offset_namelen(fdt, path, strlen(path));
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+ const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
+ const char *nameptr;
+ int err;
+
+ if (fdt_chk_extra() &&
+ (((err = fdt_ro_probe_(fdt)) < 0)
+ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
+ goto fail;
+
+ nameptr = nh->name;
+
+ if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+ /*
+ * For old FDT versions, match the naming conventions of V16:
+ * give only the leaf name (after all /). The actual tree
+ * contents are loosely checked.
+ */
+ const char *leaf;
+ leaf = strrchr(nameptr, '/');
+ if (leaf == NULL) {
+ err = -FDT_ERR_BADSTRUCTURE;
+ goto fail;
+ }
+ nameptr = leaf+1;
+ }
+
+ if (len)
+ *len = strlen(nameptr);
+
+ return nameptr;
+
+ fail:
+ if (len)
+ *len = err;
+ return NULL;
+}
+
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return nextprop_(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
+ return offset;
+
+ return nextprop_(fdt, offset);
+}
+
+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ int err;
+ const struct fdt_property *prop;
+
+ if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
+
+ prop = fdt_offset_ptr_(fdt, offset);
+
+ if (lenp)
+ *lenp = fdt32_ld(&prop->len);
+
+ return prop;
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ /* Prior to version 16, properties may need realignment
+ * and this API does not work. fdt_getprop_*() will, however. */
+
+ if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVERSION;
+ return NULL;
+ }
+
+ return fdt_get_property_by_offset_(fdt, offset, lenp);
+}
+
+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen,
+ int *lenp,
+ int *poffset)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+ if (fdt_chk_extra() && !prop) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+ if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ name, namelen)) {
+ if (poffset)
+ *poffset = offset;
+ return prop;
+ }
+ }
+
+ if (lenp)
+ *lenp = offset;
+ return NULL;
+}
+
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ /* Prior to version 16, properties may need realignment
+ * and this API does not work. fdt_getprop_*() will, however. */
+ if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVERSION;
+ return NULL;
+ }
+
+ return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
+ NULL);
+}
+
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
+{
+ int poffset;
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
+ &poffset);
+ if (!prop)
+ return NULL;
+
+ /* Handle realignment */
+ if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ return prop->data + 4;
+ return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep) {
+ const char *name;
+ int namelen;
+
+ if (fdt_chk_extra()) {
+ name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ &namelen);
+ if (!name) {
+ if (lenp)
+ *lenp = namelen;
+ return NULL;
+ }
+ *namep = name;
+ } else {
+ *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ }
+ }
+
+ /* Handle realignment */
+ if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
+ (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ return prop->data + 4;
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+ const fdt32_t *php;
+ int len;
+
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
+
+ return fdt32_ld(php);
+}
+
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+ int pdepth = 0, p = 0;
+ int offset, depth, namelen;
+ const char *name;
+
+ FDT_RO_PROBE(fdt);
+
+ if (buflen < 2)
+ return -FDT_ERR_NOSPACE;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ while (pdepth > depth) {
+ do {
+ p--;
+ } while (buf[p-1] != '/');
+ pdepth--;
+ }
+
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
+ }
+
+ if (offset == nodeoffset) {
+ if (pdepth < (depth + 1))
+ return -FDT_ERR_NOSPACE;
+
+ if (p > 1) /* special case so that root path is "/", not "" */
+ p--;
+ buf[p] = '\0';
+ return 0;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth)
+{
+ int offset, depth;
+ int supernodeoffset = -FDT_ERR_INTERNAL;
+
+ FDT_RO_PROBE(fdt);
+
+ if (supernodedepth < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth == supernodedepth)
+ supernodeoffset = offset;
+
+ if (offset == nodeoffset) {
+ if (nodedepth)
+ *nodedepth = depth;
+
+ if (supernodedepth > depth)
+ return -FDT_ERR_NOTFOUND;
+ else
+ return supernodeoffset;
+ }
+ }
+
+ if (fdt_chk_extra()) {
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+ int nodedepth;
+ int err;
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+ if (err)
+ return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
+ return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+ if (nodedepth < 0)
+ return nodedepth;
+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ int offset;
+ const void *val;
+ int len;
+
+ FDT_RO_PROBE(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+ int offset;
+
+ if ((phandle == 0) || (phandle == -1))
+ return -FDT_ERR_BADPHANDLE;
+
+ FDT_RO_PROBE(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
+{
+ int len = strlen(str);
+ const char *p;
+
+ while (listlen >= len) {
+ if (memcmp(str, strlist, len+1) == 0)
+ return 1;
+ p = memchr(strlist, '\0', listlen);
+ if (!p)
+ return 0; /* malformed strlist.. */
+ listlen -= (p-strlist) + 1;
+ strlist = p + 1;
+ }
+ return 0;
+}
+
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
+{
+ const char *list, *end;
+ int length, count = 0;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list)
+ return length;
+
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end)
+ return -FDT_ERR_BADVALUE;
+
+ list += length;
+ count++;
+ }
+
+ return count;
+}
+
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+ const char *string)
+{
+ int length, len, idx = 0;
+ const char *list, *end;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list)
+ return length;
+
+ len = strlen(string) + 1;
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end)
+ return -FDT_ERR_BADVALUE;
+
+ if (length == len && memcmp(list, string, length) == 0)
+ return idx;
+
+ list += length;
+ idx++;
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+ const char *property, int idx,
+ int *lenp)
+{
+ const char *list, *end;
+ int length;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list) {
+ if (lenp)
+ *lenp = length;
+
+ return NULL;
+ }
+
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVALUE;
+
+ return NULL;
+ }
+
+ if (idx == 0) {
+ if (lenp)
+ *lenp = length - 1;
+
+ return list;
+ }
+
+ list += length;
+ idx--;
+ }
+
+ if (lenp)
+ *lenp = -FDT_ERR_NOTFOUND;
+
+ return NULL;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible)
+{
+ const void *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+ if (!prop)
+ return len;
+
+ return !fdt_stringlist_contains(prop, len, compatible);
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible)
+{
+ int offset, err;
+
+ FDT_RO_PROBE(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_node_check_compatible(), then if
+ * that didn't find what we want, we scan over them again
+ * making our way to the next node. Still it's the easiest to
+ * implement approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ err = fdt_node_check_compatible(fdt, offset, compatible);
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+ return err;
+ else if (err == 0)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+#if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0
+int fdt_check_full(const void *fdt, size_t bufsize)
+{
+ int err;
+ int num_memrsv;
+ int offset, nextoffset = 0;
+ uint32_t tag;
+ unsigned depth = 0;
+ const void *prop;
+ const char *propname;
+
+ if (bufsize < FDT_V1_SIZE)
+ return -FDT_ERR_TRUNCATED;
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ return err;
+ if (bufsize < fdt_totalsize(fdt))
+ return -FDT_ERR_TRUNCATED;
+
+ num_memrsv = fdt_num_mem_rsv(fdt);
+ if (num_memrsv < 0)
+ return num_memrsv;
+
+ while (1) {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ if (nextoffset < 0)
+ return nextoffset;
+
+ switch (tag) {
+ case FDT_NOP:
+ break;
+
+ case FDT_END:
+ if (depth != 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ return 0;
+
+ case FDT_BEGIN_NODE:
+ depth++;
+ if (depth > INT_MAX)
+ return -FDT_ERR_BADSTRUCTURE;
+ break;
+
+ case FDT_END_NODE:
+ if (depth == 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ depth--;
+ break;
+
+ case FDT_PROP:
+ prop = fdt_getprop_by_offset(fdt, offset, &propname,
+ &err);
+ if (!prop)
+ return err;
+ break;
+
+ default:
+ return -FDT_ERR_INTERNAL;
+ }
+ }
+}
+#endif
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
new file mode 100644
index 00000000..aafded07
--- /dev/null
+++ b/lib/libfdt/fdt_rw.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_rw.c"
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
new file mode 100644
index 00000000..408a8832
--- /dev/null
+++ b/lib/libfdt/fdt_strerror.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_strerror.c"
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
new file mode 100644
index 00000000..0da3ed92
--- /dev/null
+++ b/lib/libfdt/fdt_sw.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_sw.c"
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
new file mode 100644
index 00000000..6a771d06
--- /dev/null
+++ b/lib/libfdt/fdt_wip.c
@@ -0,0 +1,2 @@
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_wip.c"
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
new file mode 100644
index 00000000..5197c5d6
--- /dev/null
+++ b/lib/libfdt/libfdt_internal.h
@@ -0,0 +1 @@
+#include "../../scripts/dtc/libfdt/libfdt_internal.h"
diff --git a/lib/libfdt/test_libfdt.py b/lib/libfdt/test_libfdt.py
new file mode 100644
index 00000000..14d0da4f
--- /dev/null
+++ b/lib/libfdt/test_libfdt.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import os
+import sys
+
+our_path = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(our_path, '../../b/sandbox_spl/tools'))
+
+import libfdt
+
+with open('b/sandbox_spl/u-boot.dtb') as fd:
+ fdt = fd.read()
+
+print libfdt.fdt_path_offset(fdt, "/aliases")
diff --git a/lib/linux_compat.c b/lib/linux_compat.c
new file mode 100644
index 00000000..3f440dea
--- /dev/null
+++ b/lib/linux_compat.c
@@ -0,0 +1,61 @@
+
+#include <common.h>
+#include <memalign.h>
+#include <linux/compat.h>
+
+struct p_current cur = {
+ .pid = 1,
+};
+__maybe_unused struct p_current *current = &cur;
+
+unsigned long copy_from_user(void *dest, const void *src,
+ unsigned long count)
+{
+ memcpy((void *)dest, (void *)src, count);
+ return 0;
+}
+
+void *kmalloc(size_t size, int flags)
+{
+ void *p;
+
+ p = malloc_cache_aligned(size);
+ if (p && flags & __GFP_ZERO)
+ memset(p, 0, size);
+
+ return p;
+}
+
+struct kmem_cache *get_mem(int element_sz)
+{
+ struct kmem_cache *ret;
+
+ ret = memalign(ARCH_DMA_MINALIGN, sizeof(struct kmem_cache));
+ ret->sz = element_sz;
+
+ return ret;
+}
+
+void *kmem_cache_alloc(struct kmem_cache *obj, int flag)
+{
+ return malloc_cache_aligned(obj->sz);
+}
+
+/**
+ * kmemdup - duplicate region of memory
+ *
+ * @src: memory region to duplicate
+ * @len: memory region length
+ * @gfp: GFP mask to use
+ *
+ * Return: newly allocated copy of @src or %NULL in case of error
+ */
+void *kmemdup(const void *src, size_t len, gfp_t gfp)
+{
+ void *p;
+
+ p = kmalloc(len, gfp);
+ if (p)
+ memcpy(p, src, len);
+ return p;
+}
diff --git a/lib/linux_string.c b/lib/linux_string.c
new file mode 100644
index 00000000..d5a5e08d
--- /dev/null
+++ b/lib/linux_string.c
@@ -0,0 +1,51 @@
+/*
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifdef USE_HOSTCC
+#include <stdio.h>
+#endif
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+
+/**
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ */
+char *skip_spaces(const char *str)
+{
+ while (isspace(*str))
+ ++str;
+ return (char *)str;
+}
+
+/**
+ * strim - Removes leading and trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns a pointer to the first non-whitespace
+ * character in @s.
+ */
+char *strim(char *s)
+{
+ size_t size;
+ char *end;
+
+ s = skip_spaces(s);
+ size = strlen(s);
+ if (!size)
+ return s;
+
+ end = s + size - 1;
+ while (end >= s && isspace(*end))
+ end--;
+ *(end + 1) = '\0';
+
+ return s;
+}
diff --git a/lib/list_sort.c b/lib/list_sort.c
new file mode 100644
index 00000000..e841da53
--- /dev/null
+++ b/lib/list_sort.c
@@ -0,0 +1,297 @@
+#ifndef __UBOOT__
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#else
+#include <linux/compat.h>
+#include <common.h>
+#include <malloc.h>
+#endif
+#include <linux/list.h>
+#include <linux/list_sort.h>
+
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+static struct list_head *merge(void *priv,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b),
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head head, *tail = &head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(priv, a, b) <= 0) {
+ tail->next = a;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a?:b;
+ return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure. This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+static void merge_and_restore_back_links(void *priv,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b),
+ struct list_head *head,
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head *tail = head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(priv, a, b) <= 0) {
+ tail->next = a;
+ a->prev = tail;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b->prev = tail;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a ? : b;
+
+ do {
+ /*
+ * In worst cases this loop may run many iterations.
+ * Continue callbacks to the client even though no
+ * element comparison is needed, so the client's cmp()
+ * routine can invoke cond_resched() periodically.
+ */
+ (*cmp)(priv, tail->next, tail->next);
+
+ tail->next->prev = tail;
+ tail = tail->next;
+ } while (tail->next);
+
+ tail->next = head;
+ head->prev = tail;
+}
+
+/**
+ * list_sort - sort a list
+ * @priv: private data, opaque to list_sort(), passed to @cmp
+ * @head: the list to sort
+ * @cmp: the elements comparison function
+ *
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
+ *
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
+ */
+void list_sort(void *priv, struct list_head *head,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b))
+{
+ struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+ -- last slot is a sentinel */
+ int lev; /* index into part[] */
+ int max_lev = 0;
+ struct list_head *list;
+
+ if (list_empty(head))
+ return;
+
+ memset(part, 0, sizeof(part));
+
+ head->prev->next = NULL;
+ list = head->next;
+
+ while (list) {
+ struct list_head *cur = list;
+ list = list->next;
+ cur->next = NULL;
+
+ for (lev = 0; part[lev]; lev++) {
+ cur = merge(priv, cmp, part[lev], cur);
+ part[lev] = NULL;
+ }
+ if (lev > max_lev) {
+ if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
+ printk_once(KERN_DEBUG "list passed to"
+ " list_sort() too long for"
+ " efficiency\n");
+ lev--;
+ }
+ max_lev = lev;
+ }
+ part[lev] = cur;
+ }
+
+ for (lev = 0; lev < max_lev; lev++)
+ if (part[lev])
+ list = merge(priv, cmp, part[lev], list);
+
+ merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+}
+EXPORT_SYMBOL(list_sort);
+
+#ifdef CONFIG_TEST_LIST_SORT
+
+#include <linux/random.h>
+
+/*
+ * The pattern of set bits in the list length determines which cases
+ * are hit in list_sort().
+ */
+#define TEST_LIST_LEN (512+128+2) /* not including head */
+
+#define TEST_POISON1 0xDEADBEEF
+#define TEST_POISON2 0xA324354C
+
+struct debug_el {
+ unsigned int poison1;
+ struct list_head list;
+ unsigned int poison2;
+ int value;
+ unsigned serial;
+};
+
+/* Array, containing pointers to all elements in the test list */
+static struct debug_el **elts __initdata;
+
+static int __init check(struct debug_el *ela, struct debug_el *elb)
+{
+ if (ela->serial >= TEST_LIST_LEN) {
+ printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+ ela->serial);
+ return -EINVAL;
+ }
+ if (elb->serial >= TEST_LIST_LEN) {
+ printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+ elb->serial);
+ return -EINVAL;
+ }
+ if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
+ printk(KERN_ERR "list_sort_test: error: phantom element\n");
+ return -EINVAL;
+ }
+ if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
+ printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+ ela->poison1, ela->poison2);
+ return -EINVAL;
+ }
+ if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
+ printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+ elb->poison1, elb->poison2);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+ struct debug_el *ela, *elb;
+
+ ela = container_of(a, struct debug_el, list);
+ elb = container_of(b, struct debug_el, list);
+
+ check(ela, elb);
+ return ela->value - elb->value;
+}
+
+static int __init list_sort_test(void)
+{
+ int i, count = 1, err = -EINVAL;
+ struct debug_el *el;
+ struct list_head *cur, *tmp;
+ LIST_HEAD(head);
+
+ printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n");
+
+ elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL);
+ if (!elts) {
+ printk(KERN_ERR "list_sort_test: error: cannot allocate "
+ "memory\n");
+ goto exit;
+ }
+
+ for (i = 0; i < TEST_LIST_LEN; i++) {
+ el = kmalloc(sizeof(*el), GFP_KERNEL);
+ if (!el) {
+ printk(KERN_ERR "list_sort_test: error: cannot "
+ "allocate memory\n");
+ goto exit;
+ }
+ /* force some equivalencies */
+ el->value = prandom_u32() % (TEST_LIST_LEN / 3);
+ el->serial = i;
+ el->poison1 = TEST_POISON1;
+ el->poison2 = TEST_POISON2;
+ elts[i] = el;
+ list_add_tail(&el->list, &head);
+ }
+
+ list_sort(NULL, &head, cmp);
+
+ for (cur = head.next; cur->next != &head; cur = cur->next) {
+ struct debug_el *el1;
+ int cmp_result;
+
+ if (cur->next->prev != cur) {
+ printk(KERN_ERR "list_sort_test: error: list is "
+ "corrupted\n");
+ goto exit;
+ }
+
+ cmp_result = cmp(NULL, cur, cur->next);
+ if (cmp_result > 0) {
+ printk(KERN_ERR "list_sort_test: error: list is not "
+ "sorted\n");
+ goto exit;
+ }
+
+ el = container_of(cur, struct debug_el, list);
+ el1 = container_of(cur->next, struct debug_el, list);
+ if (cmp_result == 0 && el->serial >= el1->serial) {
+ printk(KERN_ERR "list_sort_test: error: order of "
+ "equivalent elements not preserved\n");
+ goto exit;
+ }
+
+ if (check(el, el1)) {
+ printk(KERN_ERR "list_sort_test: error: element check "
+ "failed\n");
+ goto exit;
+ }
+ count++;
+ }
+
+ if (count != TEST_LIST_LEN) {
+ printk(KERN_ERR "list_sort_test: error: bad list length %d",
+ count);
+ goto exit;
+ }
+
+ err = 0;
+exit:
+ kfree(elts);
+ list_for_each_safe(cur, tmp, &head) {
+ list_del(cur);
+ kfree(container_of(cur, struct debug_el, list));
+ }
+ return err;
+}
+module_init(list_sort_test);
+#endif /* CONFIG_TEST_LIST_SORT */
diff --git a/lib/lmb.c b/lib/lmb.c
new file mode 100644
index 00000000..b3b84e4d
--- /dev/null
+++ b/lib/lmb.c
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Procedures for maintaining information about logical memory blocks.
+ *
+ * Peter Bergner, IBM Corp. June 2001.
+ * Copyright (C) 2001 Peter Bergner.
+ */
+
+#include <common.h>
+#include <lmb.h>
+
+#define LMB_ALLOC_ANYWHERE 0
+
+void lmb_dump_all(struct lmb *lmb)
+{
+#ifdef DEBUG
+ unsigned long i;
+
+ debug("lmb_dump_all:\n");
+ debug(" memory.cnt = 0x%lx\n", lmb->memory.cnt);
+ debug(" memory.size = 0x%llx\n",
+ (unsigned long long)lmb->memory.size);
+ for (i = 0; i < lmb->memory.cnt; i++) {
+ debug(" memory.reg[0x%lx].base = 0x%llx\n", i,
+ (unsigned long long)lmb->memory.region[i].base);
+ debug(" .size = 0x%llx\n",
+ (unsigned long long)lmb->memory.region[i].size);
+ }
+
+ debug("\n reserved.cnt = 0x%lx\n",
+ lmb->reserved.cnt);
+ debug(" reserved.size = 0x%llx\n",
+ (unsigned long long)lmb->reserved.size);
+ for (i = 0; i < lmb->reserved.cnt; i++) {
+ debug(" reserved.reg[0x%lx].base = 0x%llx\n", i,
+ (unsigned long long)lmb->reserved.region[i].base);
+ debug(" .size = 0x%llx\n",
+ (unsigned long long)lmb->reserved.region[i].size);
+ }
+#endif /* DEBUG */
+}
+
+static long lmb_addrs_overlap(phys_addr_t base1, phys_size_t size1,
+ phys_addr_t base2, phys_size_t size2)
+{
+ const phys_addr_t base1_end = base1 + size1 - 1;
+ const phys_addr_t base2_end = base2 + size2 - 1;
+
+ return ((base1 <= base2_end) && (base2 <= base1_end));
+}
+
+static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1,
+ phys_addr_t base2, phys_size_t size2)
+{
+ if (base2 == base1 + size1)
+ return 1;
+ else if (base1 == base2 + size2)
+ return -1;
+
+ return 0;
+}
+
+static long lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1,
+ unsigned long r2)
+{
+ phys_addr_t base1 = rgn->region[r1].base;
+ phys_size_t size1 = rgn->region[r1].size;
+ phys_addr_t base2 = rgn->region[r2].base;
+ phys_size_t size2 = rgn->region[r2].size;
+
+ return lmb_addrs_adjacent(base1, size1, base2, size2);
+}
+
+static void lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+{
+ unsigned long i;
+
+ for (i = r; i < rgn->cnt - 1; i++) {
+ rgn->region[i].base = rgn->region[i + 1].base;
+ rgn->region[i].size = rgn->region[i + 1].size;
+ }
+ rgn->cnt--;
+}
+
+/* Assumption: base addr of region 1 < base addr of region 2 */
+static void lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1,
+ unsigned long r2)
+{
+ rgn->region[r1].size += rgn->region[r2].size;
+ lmb_remove_region(rgn, r2);
+}
+
+void lmb_init(struct lmb *lmb)
+{
+ lmb->memory.cnt = 0;
+ lmb->memory.size = 0;
+ lmb->reserved.cnt = 0;
+ lmb->reserved.size = 0;
+}
+
+static void lmb_reserve_common(struct lmb *lmb, void *fdt_blob)
+{
+ arch_lmb_reserve(lmb);
+ board_lmb_reserve(lmb);
+
+ if (IMAGE_ENABLE_OF_LIBFDT && fdt_blob)
+ boot_fdt_add_mem_rsv_regions(lmb, fdt_blob);
+}
+
+/* Initialize the struct, add memory and call arch/board reserve functions */
+void lmb_init_and_reserve(struct lmb *lmb, bd_t *bd, void *fdt_blob)
+{
+#ifdef CONFIG_NR_DRAM_BANKS
+ int i;
+#endif
+
+ lmb_init(lmb);
+#ifdef CONFIG_NR_DRAM_BANKS
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ if (bd->bi_dram[i].size) {
+ lmb_add(lmb, bd->bi_dram[i].start,
+ bd->bi_dram[i].size);
+ }
+ }
+#else
+ if (bd->bi_memsize)
+ lmb_add(lmb, bd->bi_memstart, bd->bi_memsize);
+#endif
+ lmb_reserve_common(lmb, fdt_blob);
+}
+
+/* Initialize the struct, add memory and call arch/board reserve functions */
+void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
+ phys_size_t size, void *fdt_blob)
+{
+ lmb_init(lmb);
+ lmb_add(lmb, base, size);
+ lmb_reserve_common(lmb, fdt_blob);
+}
+
+/* This routine called with relocation disabled. */
+static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t size)
+{
+ unsigned long coalesced = 0;
+ long adjacent, i;
+
+ if (rgn->cnt == 0) {
+ rgn->region[0].base = base;
+ rgn->region[0].size = size;
+ rgn->cnt = 1;
+ return 0;
+ }
+
+ /* First try and coalesce this LMB with another. */
+ for (i = 0; i < rgn->cnt; i++) {
+ phys_addr_t rgnbase = rgn->region[i].base;
+ phys_size_t rgnsize = rgn->region[i].size;
+
+ if ((rgnbase == base) && (rgnsize == size))
+ /* Already have this region, so we're done */
+ return 0;
+
+ adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
+ if (adjacent > 0) {
+ rgn->region[i].base -= size;
+ rgn->region[i].size += size;
+ coalesced++;
+ break;
+ } else if (adjacent < 0) {
+ rgn->region[i].size += size;
+ coalesced++;
+ break;
+ } else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) {
+ /* regions overlap */
+ return -1;
+ }
+ }
+
+ if ((i < rgn->cnt - 1) && lmb_regions_adjacent(rgn, i, i + 1)) {
+ lmb_coalesce_regions(rgn, i, i + 1);
+ coalesced++;
+ }
+
+ if (coalesced)
+ return coalesced;
+ if (rgn->cnt >= MAX_LMB_REGIONS)
+ return -1;
+
+ /* Couldn't coalesce the LMB, so add it to the sorted table. */
+ for (i = rgn->cnt-1; i >= 0; i--) {
+ if (base < rgn->region[i].base) {
+ rgn->region[i + 1].base = rgn->region[i].base;
+ rgn->region[i + 1].size = rgn->region[i].size;
+ } else {
+ rgn->region[i + 1].base = base;
+ rgn->region[i + 1].size = size;
+ break;
+ }
+ }
+
+ if (base < rgn->region[0].base) {
+ rgn->region[0].base = base;
+ rgn->region[0].size = size;
+ }
+
+ rgn->cnt++;
+
+ return 0;
+}
+
+/* This routine may be called with relocation disabled. */
+long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+ struct lmb_region *_rgn = &(lmb->memory);
+
+ return lmb_add_region(_rgn, base, size);
+}
+
+long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+ struct lmb_region *rgn = &(lmb->reserved);
+ phys_addr_t rgnbegin, rgnend;
+ phys_addr_t end = base + size - 1;
+ int i;
+
+ rgnbegin = rgnend = 0; /* supress gcc warnings */
+
+ /* Find the region where (base, size) belongs to */
+ for (i = 0; i < rgn->cnt; i++) {
+ rgnbegin = rgn->region[i].base;
+ rgnend = rgnbegin + rgn->region[i].size - 1;
+
+ if ((rgnbegin <= base) && (end <= rgnend))
+ break;
+ }
+
+ /* Didn't find the region */
+ if (i == rgn->cnt)
+ return -1;
+
+ /* Check to see if we are removing entire region */
+ if ((rgnbegin == base) && (rgnend == end)) {
+ lmb_remove_region(rgn, i);
+ return 0;
+ }
+
+ /* Check to see if region is matching at the front */
+ if (rgnbegin == base) {
+ rgn->region[i].base = end + 1;
+ rgn->region[i].size -= size;
+ return 0;
+ }
+
+ /* Check to see if the region is matching at the end */
+ if (rgnend == end) {
+ rgn->region[i].size -= size;
+ return 0;
+ }
+
+ /*
+ * We need to split the entry - adjust the current one to the
+ * beginging of the hole and add the region after hole.
+ */
+ rgn->region[i].size = base - rgn->region[i].base;
+ return lmb_add_region(rgn, end + 1, rgnend - end);
+}
+
+long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+ struct lmb_region *_rgn = &(lmb->reserved);
+
+ return lmb_add_region(_rgn, base, size);
+}
+
+static long lmb_overlaps_region(struct lmb_region *rgn, phys_addr_t base,
+ phys_size_t size)
+{
+ unsigned long i;
+
+ for (i = 0; i < rgn->cnt; i++) {
+ phys_addr_t rgnbase = rgn->region[i].base;
+ phys_size_t rgnsize = rgn->region[i].size;
+ if (lmb_addrs_overlap(base, size, rgnbase, rgnsize))
+ break;
+ }
+
+ return (i < rgn->cnt) ? i : -1;
+}
+
+phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align)
+{
+ return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE);
+}
+
+phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr)
+{
+ phys_addr_t alloc;
+
+ alloc = __lmb_alloc_base(lmb, size, align, max_addr);
+
+ if (alloc == 0)
+ printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
+ (ulong)size, (ulong)max_addr);
+
+ return alloc;
+}
+
+static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size)
+{
+ return addr & ~(size - 1);
+}
+
+phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr)
+{
+ long i, rgn;
+ phys_addr_t base = 0;
+ phys_addr_t res_base;
+
+ for (i = lmb->memory.cnt - 1; i >= 0; i--) {
+ phys_addr_t lmbbase = lmb->memory.region[i].base;
+ phys_size_t lmbsize = lmb->memory.region[i].size;
+
+ if (lmbsize < size)
+ continue;
+ if (max_addr == LMB_ALLOC_ANYWHERE)
+ base = lmb_align_down(lmbbase + lmbsize - size, align);
+ else if (lmbbase < max_addr) {
+ base = lmbbase + lmbsize;
+ if (base < lmbbase)
+ base = -1;
+ base = min(base, max_addr);
+ base = lmb_align_down(base - size, align);
+ } else
+ continue;
+
+ while (base && lmbbase <= base) {
+ rgn = lmb_overlaps_region(&lmb->reserved, base, size);
+ if (rgn < 0) {
+ /* This area isn't reserved, take it */
+ if (lmb_add_region(&lmb->reserved, base,
+ size) < 0)
+ return 0;
+ return base;
+ }
+ res_base = lmb->reserved.region[rgn].base;
+ if (res_base < size)
+ break;
+ base = lmb_align_down(res_base - size, align);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Try to allocate a specific address range: must be in defined memory but not
+ * reserved
+ */
+phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+ long rgn;
+
+ /* Check if the requested address is in one of the memory regions */
+ rgn = lmb_overlaps_region(&lmb->memory, base, size);
+ if (rgn >= 0) {
+ /*
+ * Check if the requested end address is in the same memory
+ * region we found.
+ */
+ if (lmb_addrs_overlap(lmb->memory.region[rgn].base,
+ lmb->memory.region[rgn].size,
+ base + size - 1, 1)) {
+ /* ok, reserve the memory */
+ if (lmb_reserve(lmb, base, size) >= 0)
+ return base;
+ }
+ }
+ return 0;
+}
+
+/* Return number of bytes from a given address that are free */
+phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr)
+{
+ int i;
+ long rgn;
+
+ /* check if the requested address is in the memory regions */
+ rgn = lmb_overlaps_region(&lmb->memory, addr, 1);
+ if (rgn >= 0) {
+ for (i = 0; i < lmb->reserved.cnt; i++) {
+ if (addr < lmb->reserved.region[i].base) {
+ /* first reserved range > requested address */
+ return lmb->reserved.region[i].base - addr;
+ }
+ if (lmb->reserved.region[i].base +
+ lmb->reserved.region[i].size > addr) {
+ /* requested addr is in this reserved range */
+ return 0;
+ }
+ }
+ /* if we come here: no reserved ranges above requested addr */
+ return lmb->memory.region[lmb->memory.cnt - 1].base +
+ lmb->memory.region[lmb->memory.cnt - 1].size - addr;
+ }
+ return 0;
+}
+
+int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr)
+{
+ int i;
+
+ for (i = 0; i < lmb->reserved.cnt; i++) {
+ phys_addr_t upper = lmb->reserved.region[i].base +
+ lmb->reserved.region[i].size - 1;
+ if ((addr >= lmb->reserved.region[i].base) && (addr <= upper))
+ return 1;
+ }
+ return 0;
+}
+
+__weak void board_lmb_reserve(struct lmb *lmb)
+{
+ /* please define platform specific board_lmb_reserve() */
+}
+
+__weak void arch_lmb_reserve(struct lmb *lmb)
+{
+ /* please define platform specific arch_lmb_reserve() */
+}
diff --git a/lib/lz4.c b/lib/lz4.c
new file mode 100644
index 00000000..046c34e3
--- /dev/null
+++ b/lib/lz4.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2015, Yann Collet.
+
+ You can contact the author at :
+ - LZ4 source repository : https://github.com/Cyan4973/lz4
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+
+
+/**************************************
+* Reading and writing into memory
+**************************************/
+
+/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
+static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
+{
+ BYTE* d = (BYTE*)dstPtr;
+ const BYTE* s = (const BYTE*)srcPtr;
+ BYTE* e = (BYTE*)dstEnd;
+ do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
+}
+
+
+/**************************************
+* Common Constants
+**************************************/
+#define MINMATCH 4
+
+#define COPYLENGTH 8
+#define LASTLITERALS 5
+#define MFLIMIT (COPYLENGTH+MINMATCH)
+static const int LZ4_minLength = (MFLIMIT+1);
+
+#define KB *(1 <<10)
+#define MB *(1 <<20)
+#define GB *(1U<<30)
+
+#define MAXD_LOG 16
+#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
+
+#define ML_BITS 4
+#define ML_MASK ((1U<<ML_BITS)-1)
+#define RUN_BITS (8-ML_BITS)
+#define RUN_MASK ((1U<<RUN_BITS)-1)
+
+
+/**************************************
+* Local Structures and types
+**************************************/
+typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
+typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
+typedef enum { full = 0, partial = 1 } earlyEnd_directive;
+
+
+
+/*******************************
+* Decompression functions
+*******************************/
+/*
+ * This generic decompression function cover all use cases.
+ * It shall be instantiated several times, using different sets of directives
+ * Note that it is essential this generic function is really inlined,
+ * in order to remove useless branches during compilation optimization.
+ */
+FORCE_INLINE int LZ4_decompress_generic(
+ const char* const source,
+ char* const dest,
+ int inputSize,
+ int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
+
+ int endOnInput, /* endOnOutputSize, endOnInputSize */
+ int partialDecoding, /* full, partial */
+ int targetOutputSize, /* only used if partialDecoding==partial */
+ int dict, /* noDict, withPrefix64k, usingExtDict */
+ const BYTE* const lowPrefix, /* == dest if dict == noDict */
+ const BYTE* const dictStart, /* only if dict==usingExtDict */
+ const size_t dictSize /* note : = 0 if noDict */
+ )
+{
+ /* Local Variables */
+ const BYTE* ip = (const BYTE*) source;
+ const BYTE* const iend = ip + inputSize;
+
+ BYTE* op = (BYTE*) dest;
+ BYTE* const oend = op + outputSize;
+ BYTE* cpy;
+ BYTE* oexit = op + targetOutputSize;
+ const BYTE* const lowLimit = lowPrefix - dictSize;
+
+ const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
+ const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
+ const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
+
+ const int safeDecode = (endOnInput==endOnInputSize);
+ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
+
+
+ /* Special cases */
+ if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
+ if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
+ if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
+
+
+ /* Main Loop */
+ while (1)
+ {
+ unsigned token;
+ size_t length;
+ const BYTE* match;
+
+ /* get literal length */
+ token = *ip++;
+ if ((length=(token>>ML_BITS)) == RUN_MASK)
+ {
+ unsigned s;
+ do
+ {
+ s = *ip++;
+ length += s;
+ }
+ while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));
+ if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
+ if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
+ }
+
+ /* copy literals */
+ cpy = op+length;
+ if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
+ || ((!endOnInput) && (cpy>oend-COPYLENGTH)))
+ {
+ if (partialDecoding)
+ {
+ if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
+ if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
+ }
+ else
+ {
+ if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
+ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
+ }
+ memcpy(op, ip, length);
+ ip += length;
+ op += length;
+ break; /* Necessarily EOF, due to parsing restrictions */
+ }
+ LZ4_wildCopy(op, ip, cpy);
+ ip += length; op = cpy;
+
+ /* get offset */
+ match = cpy - LZ4_readLE16(ip); ip+=2;
+ if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
+
+ /* get matchlength */
+ length = token & ML_MASK;
+ if (length == ML_MASK)
+ {
+ unsigned s;
+ do
+ {
+ if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
+ s = *ip++;
+ length += s;
+ } while (s==255);
+ if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
+ }
+ length += MINMATCH;
+
+ /* check external dictionary */
+ if ((dict==usingExtDict) && (match < lowPrefix))
+ {
+ if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
+
+ if (length <= (size_t)(lowPrefix-match))
+ {
+ /* match can be copied as a single segment from external dictionary */
+ match = dictEnd - (lowPrefix-match);
+ memmove(op, match, length); op += length;
+ }
+ else
+ {
+ /* match encompass external dictionary and current segment */
+ size_t copySize = (size_t)(lowPrefix-match);
+ memcpy(op, dictEnd - copySize, copySize);
+ op += copySize;
+ copySize = length - copySize;
+ if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
+ {
+ BYTE* const endOfMatch = op + copySize;
+ const BYTE* copyFrom = lowPrefix;
+ while (op < endOfMatch) *op++ = *copyFrom++;
+ }
+ else
+ {
+ memcpy(op, lowPrefix, copySize);
+ op += copySize;
+ }
+ }
+ continue;
+ }
+
+ /* copy repeated sequence */
+ cpy = op + length;
+ if (unlikely((op-match)<8))
+ {
+ const size_t dec64 = dec64table[op-match];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[op-match];
+ LZ4_copy4(op+4, match);
+ op += 8; match -= dec64;
+ } else { LZ4_copy8(op, match); op+=8; match+=8; }
+
+ if (unlikely(cpy>oend-12))
+ {
+ if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
+ if (op < oend-8)
+ {
+ LZ4_wildCopy(op, match, oend-8);
+ match += (oend-8) - op;
+ op = oend-8;
+ }
+ while (op<cpy) *op++ = *match++;
+ }
+ else
+ LZ4_wildCopy(op, match, cpy);
+ op=cpy; /* correction */
+ }
+
+ /* end of decoding */
+ if (endOnInput)
+ return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
+ else
+ return (int) (((const char*)ip)-source); /* Nb of input bytes read */
+
+ /* Overflow error detected */
+_output_error:
+ return (int) (-(((const char*)ip)-source))-1;
+}
diff --git a/lib/lz4_wrapper.c b/lib/lz4_wrapper.c
new file mode 100644
index 00000000..1e1e8d50
--- /dev/null
+++ b/lib/lz4_wrapper.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL 2.0+ OR BSD-3-Clause
+/*
+ * Copyright 2015 Google Inc.
+ */
+
+#include <common.h>
+#include <compiler.h>
+#include <image.h>
+#include <lz4.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+static u16 LZ4_readLE16(const void *src) { return le16_to_cpu(*(u16 *)src); }
+static void LZ4_copy4(void *dst, const void *src) { *(u32 *)dst = *(u32 *)src; }
+static void LZ4_copy8(void *dst, const void *src) { *(u64 *)dst = *(u64 *)src; }
+
+typedef uint8_t BYTE;
+typedef uint16_t U16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+
+#define FORCE_INLINE static inline __attribute__((always_inline))
+
+/* Unaltered (except removing unrelated code) from github.com/Cyan4973/lz4. */
+#include "lz4.c" /* #include for inlining, do not link! */
+
+struct lz4_frame_header {
+ u32 magic;
+ union {
+ u8 flags;
+ struct {
+ u8 reserved0:2;
+ u8 has_content_checksum:1;
+ u8 has_content_size:1;
+ u8 has_block_checksum:1;
+ u8 independent_blocks:1;
+ u8 version:2;
+ };
+ };
+ union {
+ u8 block_descriptor;
+ struct {
+ u8 reserved1:4;
+ u8 max_block_size:3;
+ u8 reserved2:1;
+ };
+ };
+ /* + u64 content_size iff has_content_size is set */
+ /* + u8 header_checksum */
+} __packed;
+
+struct lz4_block_header {
+ union {
+ u32 raw;
+ struct {
+ u32 size:31;
+ u32 not_compressed:1;
+ };
+ };
+ /* + size bytes of data */
+ /* + u32 block_checksum iff has_block_checksum is set */
+} __packed;
+
+int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn)
+{
+ const void *end = dst + *dstn;
+ const void *in = src;
+ void *out = dst;
+ int has_block_checksum;
+ int ret;
+ *dstn = 0;
+
+ { /* With in-place decompression the header may become invalid later. */
+ const struct lz4_frame_header *h = in;
+
+ if (srcn < sizeof(*h) + sizeof(u64) + sizeof(u8))
+ return -EINVAL; /* input overrun */
+
+ /* We assume there's always only a single, standard frame. */
+ if (le32_to_cpu(h->magic) != LZ4F_MAGIC || h->version != 1)
+ return -EPROTONOSUPPORT; /* unknown format */
+ if (h->reserved0 || h->reserved1 || h->reserved2)
+ return -EINVAL; /* reserved must be zero */
+ if (!h->independent_blocks)
+ return -EPROTONOSUPPORT; /* we can't support this yet */
+ has_block_checksum = h->has_block_checksum;
+
+ in += sizeof(*h);
+ if (h->has_content_size)
+ in += sizeof(u64);
+ in += sizeof(u8);
+ }
+
+ while (1) {
+ struct lz4_block_header b;
+
+ b.raw = le32_to_cpu(*(u32 *)in);
+ in += sizeof(struct lz4_block_header);
+
+ if (in - src + b.size > srcn) {
+ ret = -EINVAL; /* input overrun */
+ break;
+ }
+
+ if (!b.size) {
+ ret = 0; /* decompression successful */
+ break;
+ }
+
+ if (b.not_compressed) {
+ size_t size = min((ptrdiff_t)b.size, end - out);
+ memcpy(out, in, size);
+ out += size;
+ if (size < b.size) {
+ ret = -ENOBUFS; /* output overrun */
+ break;
+ }
+ } else {
+ /* constant folding essential, do not touch params! */
+ ret = LZ4_decompress_generic(in, out, b.size,
+ end - out, endOnInputSize,
+ full, 0, noDict, out, NULL, 0);
+ if (ret < 0) {
+ ret = -EPROTO; /* decompression error */
+ break;
+ }
+ out += ret;
+ }
+
+ in += b.size;
+ if (has_block_checksum)
+ in += sizeof(u32);
+ }
+
+ *dstn = out - dst;
+ return ret;
+}
diff --git a/lib/lzma/LzmaDec.c b/lib/lzma/LzmaDec.c
new file mode 100644
index 00000000..4f45f80f
--- /dev/null
+++ b/lib/lzma/LzmaDec.c
@@ -0,0 +1,1025 @@
+/* LzmaDec.c -- LZMA Decoder
+2009-09-20 : Igor Pavlov : Public domain */
+
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+#include "LzmaDec.h"
+
+#include <linux/string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+ { UPDATE_0(p); i = (i + i); A0; } else \
+ { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+ { i = 1; \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+ { UPDATE_0_CHECK; i = (i + i); A0; } else \
+ { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+ Result:
+ SZ_OK - OK
+ SZ_ERROR_DATA - Error
+ p->remainLen:
+ < kMatchSpecLenStart : normal remain
+ = kMatchSpecLenStart : finished
+ = kMatchSpecLenStart + 1 : Flush marker
+ = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ CLzmaProb *probs = p->probs;
+
+ unsigned state = p->state;
+ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+ unsigned lc = p->prop.lc;
+
+ Byte *dic = p->dic;
+ SizeT dicBufSize = p->dicBufSize;
+ SizeT dicPos = p->dicPos;
+
+ UInt32 processedPos = p->processedPos;
+ UInt32 checkDicSize = p->checkDicSize;
+ unsigned len = 0;
+
+ const Byte *buf = p->buf;
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+
+ WATCHDOG_RESET();
+
+ do
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = processedPos & pbMask;
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ unsigned symbol;
+ UPDATE_0(prob);
+ prob = probs + Literal;
+ if (checkDicSize != 0 || processedPos != 0)
+ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+ if (state < kNumLitStates)
+ {
+ state -= (state < 4) ? state : 3;
+ symbol = 1;
+
+ WATCHDOG_RESET();
+
+ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ unsigned offs = 0x100;
+ state -= (state < 10) ? 3 : 6;
+ symbol = 1;
+
+ WATCHDOG_RESET();
+
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ dic[dicPos++] = (Byte)symbol;
+ processedPos++;
+ continue;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRep + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ state += kNumStates;
+ prob = probs + LenCoder;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ if (checkDicSize == 0 && processedPos == 0)
+ return SZ_ERROR_DATA;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ processedPos++;
+ state = state < kNumLitStates ? 9 : 11;
+ continue;
+ }
+ UPDATE_1(prob);
+ }
+ else
+ {
+ UInt32 distance;
+ UPDATE_1(prob);
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = (1 << kLenNumLowBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenChoice2;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = (1 << kLenNumMidBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = (1 << kLenNumHighBits);
+ }
+ }
+ TREE_DECODE(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state >= kNumStates)
+ {
+ UInt32 distance;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+ TREE_6_DECODE(prob, distance);
+ if (distance >= kStartPosModelIndex)
+ {
+ unsigned posSlot = (unsigned)distance;
+ int numDirectBits = (int)(((distance >> 1) - 1));
+ distance = (2 | (distance & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ distance <<= numDirectBits;
+ prob = probs + SpecPos + distance - posSlot - 1;
+ {
+ UInt32 mask = 1;
+ unsigned i = 1;
+
+ WATCHDOG_RESET();
+
+ do
+ {
+ GET_BIT2(prob + i, i, ; , distance |= mask);
+ mask <<= 1;
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+
+ WATCHDOG_RESET();
+
+ do
+ {
+ NORMALIZE
+ range >>= 1;
+
+ {
+ UInt32 t;
+ code -= range;
+ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+ distance = (distance << 1) + (t + 1);
+ code += range & t;
+ }
+ /*
+ distance <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ distance |= 1;
+ }
+ */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ distance <<= kNumAlignBits;
+ {
+ unsigned i = 1;
+ GET_BIT2(prob + i, i, ; , distance |= 1);
+ GET_BIT2(prob + i, i, ; , distance |= 2);
+ GET_BIT2(prob + i, i, ; , distance |= 4);
+ GET_BIT2(prob + i, i, ; , distance |= 8);
+ }
+ if (distance == (UInt32)0xFFFFFFFF)
+ {
+ len += kMatchSpecLenStart;
+ state -= kNumStates;
+ break;
+ }
+ }
+ }
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ rep0 = distance + 1;
+ if (checkDicSize == 0)
+ {
+ if (distance >= processedPos)
+ return SZ_ERROR_DATA;
+ }
+ else if (distance >= checkDicSize)
+ return SZ_ERROR_DATA;
+ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+ }
+
+ len += kMatchMinLen;
+
+ if (limit == dicPos)
+ return SZ_ERROR_DATA;
+ {
+ SizeT rem = limit - dicPos;
+ unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+ processedPos += curLen;
+
+ len -= curLen;
+ if (pos + curLen <= dicBufSize)
+ {
+ Byte *dest = dic + dicPos;
+ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+ const Byte *lim = dest + curLen;
+ dicPos += curLen;
+
+ WATCHDOG_RESET();
+
+ do
+ *(dest) = (Byte)*(dest + src);
+ while (++dest != lim);
+ }
+ else
+ {
+
+ WATCHDOG_RESET();
+
+ do
+ {
+ dic[dicPos++] = dic[pos];
+ if (++pos == dicBufSize)
+ pos = 0;
+ }
+ while (--curLen != 0);
+ }
+ }
+ }
+ }
+ while (dicPos < limit && buf < bufLimit);
+
+ WATCHDOG_RESET();
+
+ NORMALIZE;
+ p->buf = buf;
+ p->range = range;
+ p->code = code;
+ p->remainLen = len;
+ p->dicPos = dicPos;
+ p->processedPos = processedPos;
+ p->reps[0] = rep0;
+ p->reps[1] = rep1;
+ p->reps[2] = rep2;
+ p->reps[3] = rep3;
+ p->state = state;
+
+ return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+ {
+ Byte *dic = p->dic;
+ SizeT dicPos = p->dicPos;
+ SizeT dicBufSize = p->dicBufSize;
+ unsigned len = p->remainLen;
+ UInt32 rep0 = p->reps[0];
+ if (limit - dicPos < len)
+ len = (unsigned)(limit - dicPos);
+
+ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+ p->checkDicSize = p->prop.dicSize;
+
+ p->processedPos += len;
+ p->remainLen -= len;
+ while (len-- != 0)
+ {
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ }
+ p->dicPos = dicPos;
+ }
+}
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ do
+ {
+ SizeT limit2 = limit;
+ if (p->checkDicSize == 0)
+ {
+ UInt32 rem = p->prop.dicSize - p->processedPos;
+ if (limit - p->dicPos > rem)
+ limit2 = p->dicPos + rem;
+ }
+ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+ if (p->processedPos >= p->prop.dicSize)
+ p->checkDicSize = p->prop.dicSize;
+ LzmaDec_WriteRem(p, limit);
+ }
+ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+ if (p->remainLen > kMatchSpecLenStart)
+ {
+ p->remainLen = kMatchSpecLenStart;
+ }
+ return 0;
+}
+
+typedef enum
+{
+ DUMMY_ERROR, /* unexpected end of input stream */
+ DUMMY_LIT,
+ DUMMY_MATCH,
+ DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+ const Byte *bufLimit = buf + inSize;
+ CLzmaProb *probs = p->probs;
+ unsigned state = p->state;
+ ELzmaDummy res;
+
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK
+
+ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+ prob = probs + Literal;
+ if (p->checkDicSize != 0 || p->processedPos != 0)
+ prob += (LZMA_LIT_SIZE *
+ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+ if (state < kNumLitStates)
+ {
+ unsigned symbol = 1;
+ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+ unsigned offs = 0x100;
+ unsigned symbol = 1;
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ res = DUMMY_LIT;
+ }
+ else
+ {
+ unsigned len;
+ UPDATE_1_CHECK;
+
+ prob = probs + IsRep + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ state = 0;
+ prob = probs + LenCoder;
+ res = DUMMY_MATCH;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ res = DUMMY_REP;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ NORMALIZE_CHECK;
+ return DUMMY_REP;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ }
+ state = kNumStates;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = 1 << kLenNumLowBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenChoice2;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = 1 << kLenNumMidBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = 1 << kLenNumHighBits;
+ }
+ }
+ TREE_DECODE_CHECK(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ unsigned posSlot;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+
+ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+ if (posSlot < kEndPosModelIndex)
+ {
+ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ NORMALIZE_CHECK
+ range >>= 1;
+ code -= range & (((code - range) >> 31) - 1);
+ /* if (code >= range) code -= range; */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ unsigned i = 1;
+ do
+ {
+ GET_BIT_CHECK(prob + i, i);
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ }
+ }
+ }
+ NORMALIZE_CHECK;
+ return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+ p->range = 0xFFFFFFFF;
+ p->needFlush = 0;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+ p->needFlush = 1;
+ p->remainLen = 0;
+ p->tempBufSize = 0;
+
+ if (initDic)
+ {
+ p->processedPos = 0;
+ p->checkDicSize = 0;
+ p->needInitState = 1;
+ }
+ if (initState)
+ p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+ p->dicPos = 0;
+ LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+ UInt32 i;
+ CLzmaProb *probs = p->probs;
+ for (i = 0; i < numProbs; i++)
+ probs[i] = kBitModelTotal >> 1;
+ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+ p->state = 0;
+ p->needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+ ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT inSize = *srcLen;
+ (*srcLen) = 0;
+ LzmaDec_WriteRem(p, dicLimit);
+
+ *status = LZMA_STATUS_NOT_SPECIFIED;
+
+ while (p->remainLen != kMatchSpecLenStart)
+ {
+ int checkEndMarkNow;
+
+ if (p->needFlush != 0)
+ {
+ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+ p->tempBuf[p->tempBufSize++] = *src++;
+ if (p->tempBufSize < RC_INIT_SIZE)
+ {
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (p->tempBuf[0] != 0)
+ return SZ_ERROR_DATA;
+
+ LzmaDec_InitRc(p, p->tempBuf);
+ p->tempBufSize = 0;
+ }
+
+ checkEndMarkNow = 0;
+ if (p->dicPos >= dicLimit)
+ {
+ if (p->remainLen == 0 && p->code == 0)
+ {
+ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+ return SZ_OK;
+ }
+ if (finishMode == LZMA_FINISH_ANY)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_OK;
+ }
+ if (p->remainLen != 0)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ checkEndMarkNow = 1;
+ }
+
+ if (p->needInitState)
+ LzmaDec_InitStateReal(p);
+
+ if (p->tempBufSize == 0)
+ {
+ SizeT processed;
+ const Byte *bufLimit;
+ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ memcpy(p->tempBuf, src, inSize);
+ p->tempBufSize = (unsigned)inSize;
+ (*srcLen) += inSize;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ bufLimit = src;
+ }
+ else
+ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+ p->buf = src;
+ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+ return SZ_ERROR_DATA;
+ processed = (SizeT)(p->buf - src);
+ (*srcLen) += processed;
+ src += processed;
+ inSize -= processed;
+ }
+ else
+ {
+ unsigned rem = p->tempBufSize, lookAhead = 0;
+ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+ p->tempBuf[rem++] = src[lookAhead++];
+ p->tempBufSize = rem;
+ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ (*srcLen) += lookAhead;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ }
+ p->buf = p->tempBuf;
+ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+ return SZ_ERROR_DATA;
+ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+ (*srcLen) += lookAhead;
+ src += lookAhead;
+ inSize -= lookAhead;
+ p->tempBufSize = 0;
+ }
+ }
+ if (p->code == 0)
+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
+ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT outSize = *destLen;
+ SizeT inSize = *srcLen;
+ *srcLen = *destLen = 0;
+ for (;;)
+ {
+ SizeT inSizeCur = inSize, outSizeCur, dicPos;
+ ELzmaFinishMode curFinishMode;
+ SRes res;
+ if (p->dicPos == p->dicBufSize)
+ p->dicPos = 0;
+ dicPos = p->dicPos;
+ if (outSize > p->dicBufSize - dicPos)
+ {
+ outSizeCur = p->dicBufSize;
+ curFinishMode = LZMA_FINISH_ANY;
+ }
+ else
+ {
+ outSizeCur = dicPos + outSize;
+ curFinishMode = finishMode;
+ }
+
+ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+ src += inSizeCur;
+ inSize -= inSizeCur;
+ *srcLen += inSizeCur;
+ outSizeCur = p->dicPos - dicPos;
+ memcpy(dest, p->dic + dicPos, outSizeCur);
+ dest += outSizeCur;
+ outSize -= outSizeCur;
+ *destLen += outSizeCur;
+ if (res != 0)
+ return res;
+ if (outSizeCur == 0 || outSize == 0)
+ return SZ_OK;
+ }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->probs);
+ p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->dic);
+ p->dic = 0;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+ LzmaDec_FreeProbs(p, alloc);
+ LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+ UInt32 dicSize;
+ Byte d;
+
+ if (size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_UNSUPPORTED;
+ else
+ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+
+ if (dicSize < LZMA_DIC_MIN)
+ dicSize = LZMA_DIC_MIN;
+ p->dicSize = dicSize;
+
+ d = data[0];
+ if (d >= (9 * 5 * 5))
+ return SZ_ERROR_UNSUPPORTED;
+
+ p->lc = d % 9;
+ d /= 9;
+ p->pb = d / 5;
+ p->lp = d % 5;
+
+ return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+ UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+ if (p->probs == 0 || numProbs != p->numProbs)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+ p->numProbs = numProbs;
+ if (p->probs == 0)
+ return SZ_ERROR_MEM;
+ }
+ return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ SizeT dicBufSize;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ dicBufSize = propNew.dicSize;
+ if (p->dic == 0 || dicBufSize != p->dicBufSize)
+ {
+ LzmaDec_FreeDict(p, alloc);
+ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+ if (p->dic == 0)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ return SZ_ERROR_MEM;
+ }
+ }
+ p->dicBufSize = dicBufSize;
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc)
+{
+ CLzmaDec p;
+ SRes res;
+ SizeT inSize = *srcLen;
+ SizeT outSize = *destLen;
+ *srcLen = *destLen = 0;
+ if (inSize < RC_INIT_SIZE)
+ return SZ_ERROR_INPUT_EOF;
+
+ LzmaDec_Construct(&p);
+ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+ if (res != 0)
+ return res;
+ p.dic = dest;
+ p.dicBufSize = outSize;
+
+ LzmaDec_Init(&p);
+
+ *srcLen = inSize;
+ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+ res = SZ_ERROR_INPUT_EOF;
+
+ (*destLen) = p.dicPos;
+ LzmaDec_FreeProbs(&p, alloc);
+ return res;
+}
diff --git a/lib/lzma/LzmaDec.h b/lib/lzma/LzmaDec.h
new file mode 100644
index 00000000..63aa505e
--- /dev/null
+++ b/lib/lzma/LzmaDec.h
@@ -0,0 +1,223 @@
+/* LzmaDec.h -- LZMA Decoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
+
+#include "Types.h"
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+ but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+ unsigned lc, lp, pb;
+ UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+ SZ_OK
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+ CLzmaProps prop;
+ CLzmaProb *probs;
+ Byte *dic;
+ const Byte *buf;
+ UInt32 range, code;
+ SizeT dicPos;
+ SizeT dicBufSize;
+ UInt32 processedPos;
+ UInt32 checkDicSize;
+ unsigned state;
+ UInt32 reps[4];
+ unsigned remainLen;
+ int needFlush;
+ int needInitState;
+ UInt32 numProbs;
+ unsigned tempBufSize;
+ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+ LZMA_FINISH_ANY, /* finish at any point */
+ LZMA_FINISH_END /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+ You must use LZMA_FINISH_END, when you know that current output buffer
+ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+ and output value of destLen will be less than output buffer size limit.
+ You can check status result also.
+
+ You can use multiple checks to test data integrity after full decompression:
+ 1) Check Result and "status" variable.
+ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+ You must use correct finish mode in that case. */
+
+typedef enum
+{
+ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
+ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
+ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
+ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+ 1) Dictionary Interface
+ 2) Buffer Interface
+ 3) One Call Interface
+ You can select any of these interfaces, but don't mix functions from different
+ groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+ 1) LzmaDec_Allocate / LzmaDec_Free
+ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+ You can use variant 2, if you set dictionary buffer manually.
+ For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+ SZ_OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+ dictionary to some other external buffer.
+ You must work with CLzmaDec variables directly in this interface.
+
+ STEPS:
+ LzmaDec_Constr()
+ LzmaDec_Allocate()
+ for (each new stream)
+ {
+ LzmaDec_Init()
+ while (it needs more decompression)
+ {
+ LzmaDec_DecodeToDic()
+ use data from CLzmaDec::dic and update CLzmaDec::dicPos
+ }
+ }
+ LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+
+ The decoding to internal dictionary buffer (CLzmaDec::dic).
+ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (dicLimit).
+ LZMA_FINISH_ANY - Decode just dicLimit bytes.
+ LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_NEEDS_MORE_INPUT
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+ See LzmaDec_DecodeToDic description for information about STEPS and return results,
+ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+ to work with CLzmaDec variables manually.
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc);
+
+#endif
diff --git a/lib/lzma/LzmaTools.c b/lib/lzma/LzmaTools.c
new file mode 100644
index 00000000..2537cb8f
--- /dev/null
+++ b/lib/lzma/LzmaTools.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
+ *
+ * Copyright (C) 2007-2009 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
+ *
+ * Copyright (C) 1999-2005 Igor Pavlov
+ */
+
+/*
+ * LZMA_Alone stream format:
+ *
+ * uchar Properties[5]
+ * uint64 Uncompressed size
+ * uchar data[*]
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_LZMA
+
+#define LZMA_PROPERTIES_OFFSET 0
+#define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE
+#define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t)
+
+#include "LzmaTools.h"
+#include "LzmaDec.h"
+
+#include <linux/string.h>
+#include <malloc.h>
+
+static void *SzAlloc(void *p, size_t size) { return malloc(size); }
+static void SzFree(void *p, void *address) { free(address); }
+
+int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
+ unsigned char *inStream, SizeT length)
+{
+ int res = SZ_ERROR_DATA;
+ int i;
+ ISzAlloc g_Alloc;
+
+ SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */
+ SizeT outProcessed;
+ SizeT outSize;
+ SizeT outSizeHigh;
+ ELzmaStatus state;
+ SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE);
+
+ debug ("LZMA: Image address............... 0x%p\n", inStream);
+ debug ("LZMA: Properties address.......... 0x%p\n", inStream + LZMA_PROPERTIES_OFFSET);
+ debug ("LZMA: Uncompressed size address... 0x%p\n", inStream + LZMA_SIZE_OFFSET);
+ debug ("LZMA: Compressed data address..... 0x%p\n", inStream + LZMA_DATA_OFFSET);
+ debug ("LZMA: Destination address......... 0x%p\n", outStream);
+
+ memset(&state, 0, sizeof(state));
+
+ outSize = 0;
+ outSizeHigh = 0;
+ /* Read the uncompressed size */
+ for (i = 0; i < 8; i++) {
+ unsigned char b = inStream[LZMA_SIZE_OFFSET + i];
+ if (i < 4) {
+ outSize += (UInt32)(b) << (i * 8);
+ } else {
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+ }
+
+ outSizeFull = (SizeT)outSize;
+ if (sizeof(SizeT) >= 8) {
+ /*
+ * SizeT is a 64 bit uint => We can manage files larger than 4GB!
+ *
+ */
+ outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+ } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) {
+ /*
+ * SizeT is a 32 bit uint => We cannot manage files larger than
+ * 4GB! Assume however that all 0xf values is "unknown size" and
+ * not actually a file of 2^64 bits.
+ *
+ */
+ if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) {
+ debug ("LZMA: 64bit support not enabled.\n");
+ return SZ_ERROR_DATA;
+ }
+ }
+
+ debug("LZMA: Uncompresed size............ 0x%zx\n", outSizeFull);
+ debug("LZMA: Compresed size.............. 0x%zx\n", compressedSize);
+
+ g_Alloc.Alloc = SzAlloc;
+ g_Alloc.Free = SzFree;
+
+ /* Short-circuit early if we know the buffer can't hold the results. */
+ if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull)
+ return SZ_ERROR_OUTPUT_EOF;
+
+ /* Decompress */
+ outProcessed = min(outSizeFull, *uncompressedSize);
+
+ WATCHDOG_RESET();
+
+ res = LzmaDecode(
+ outStream, &outProcessed,
+ inStream + LZMA_DATA_OFFSET, &compressedSize,
+ inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc);
+ *uncompressedSize = outProcessed;
+
+ debug("LZMA: Uncompressed ............... 0x%zx\n", outProcessed);
+
+ if (res != SZ_OK) {
+ return res;
+ }
+
+ return res;
+}
+
+#endif
diff --git a/lib/lzma/LzmaTools.h b/lib/lzma/LzmaTools.h
new file mode 100644
index 00000000..e52dfb8f
--- /dev/null
+++ b/lib/lzma/LzmaTools.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
+ *
+ * Copyright (C) 1999-2005 Igor Pavlov
+ */
+
+#ifndef __LZMA_TOOL_H__
+#define __LZMA_TOOL_H__
+
+#include <lzma/LzmaTypes.h>
+
+extern int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
+ unsigned char *inStream, SizeT length);
+#endif
diff --git a/lib/lzma/Makefile b/lib/lzma/Makefile
new file mode 100644
index 00000000..c2fd3e49
--- /dev/null
+++ b/lib/lzma/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+# Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ccflags-y += -D_LZMA_PROB32
+
+obj-y += LzmaDec.o LzmaTools.o
diff --git a/lib/lzma/README.txt b/lib/lzma/README.txt
new file mode 100644
index 00000000..23a9be28
--- /dev/null
+++ b/lib/lzma/README.txt
@@ -0,0 +1,28 @@
+The lib_lzma functionality was written by Igor Pavlov.
+The original source cames from the LZMA SDK web page:
+
+URL: http://www.7-zip.org/sdk.html
+Author: Igor Pavlov
+
+The import is made using the import_lzmasdk.sh script that:
+
+* untars the lzmaXYY.tar.bz2 file (from the download web page)
+* copies the files LzmaDec.h, Types.h, LzmaDec.c, history.txt,
+ and lzma.txt from source archive into the lib_lzma directory (pwd).
+
+Example:
+
+ . import_lzmasdk.sh ~/lzma465.tar.bz2
+
+Notice: The files from lzma sdk are _not modified_ by this script!
+
+The files LzmaTools.{c,h} are provided to export the lzmaBuffToBuffDecompress()
+function that wraps the complex LzmaDecode() function from the LZMA SDK. The
+do_bootm() function uses the lzmaBuffToBuffDecopress() function to expand the
+compressed image.
+
+The directory U-BOOT/include/lzma contains stubs files that permit to use the
+library directly from U-BOOT code without touching the original LZMA SDK's
+files.
+
+Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
diff --git a/lib/lzma/Types.h b/lib/lzma/Types.h
new file mode 100644
index 00000000..8afcba55
--- /dev/null
+++ b/lib/lzma/Types.h
@@ -0,0 +1,234 @@
+/* Types.h -- Basic types
+2010-10-09 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifdef _WIN32
+typedef DWORD WRes;
+#else
+typedef int WRes;
+#endif
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+ NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#define UINT64_CONST(n) n
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#define UINT64_CONST(n) n ## ULL
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+ Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
+} IByteIn;
+
+typedef struct
+{
+ void (*Write)(void *p, Byte b);
+} IByteOut;
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+
+typedef struct
+{
+ size_t (*Write)(void *p, const void *buf, size_t size);
+ /* Returns: result - the number of actually written bytes.
+ (result < size) means error */
+} ISeqOutStream;
+
+typedef enum
+{
+ SZ_SEEK_SET = 0,
+ SZ_SEEK_CUR = 1,
+ SZ_SEEK_END = 2
+} ESzSeek;
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ISeekInStream;
+
+typedef struct
+{
+ SRes (*Look)(void *p, const void **buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) > input(*size)) is not allowed
+ (output(*size) < input(*size)) is allowed */
+ SRes (*Skip)(void *p, size_t offset);
+ /* offset must be <= output(*size) of Look */
+
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* reads directly (without buffer). It's same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ILookInStream;
+
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+
+#define LookToRead_BUF_SIZE (1 << 14)
+
+typedef struct
+{
+ ILookInStream s;
+ ISeekInStream *realStream;
+ size_t pos;
+ size_t size;
+ Byte buf[LookToRead_BUF_SIZE];
+} CLookToRead;
+
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
+void LookToRead_Init(CLookToRead *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+typedef struct
+{
+ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+ /* Returns: result. (result != SZ_OK) means break.
+ Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+ void *(*Alloc)(void *p, size_t size);
+ void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+#ifdef _WIN32
+
+#define CHAR_PATH_SEPARATOR '\\'
+#define WCHAR_PATH_SEPARATOR L'\\'
+#define STRING_PATH_SEPARATOR "\\"
+#define WSTRING_PATH_SEPARATOR L"\\"
+
+#else
+
+#define CHAR_PATH_SEPARATOR '/'
+#define WCHAR_PATH_SEPARATOR L'/'
+#define STRING_PATH_SEPARATOR "/"
+#define WSTRING_PATH_SEPARATOR L"/"
+
+#endif
+
+#endif
diff --git a/lib/lzma/history.txt b/lib/lzma/history.txt
new file mode 100644
index 00000000..443511bd
--- /dev/null
+++ b/lib/lzma/history.txt
@@ -0,0 +1,271 @@
+HISTORY of the LZMA SDK
+-----------------------
+
+9.18 beta 2010-11-02
+-------------------------
+- New small SFX module for installers (SfxSetup).
+
+
+9.12 beta 2010-03-24
+-------------------------
+- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work,
+ if more than 10 threads were used (or more than 20 threads in some modes).
+
+
+9.11 beta 2010-03-15
+-------------------------
+- PPMd compression method support
+
+
+9.09 2009-12-12
+-------------------------
+- The bug was fixed:
+ Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c
+ incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8.
+- Some bugs were fixed
+
+
+9.06 2009-08-17
+-------------------------
+- Some changes in ANSI-C 7z Decoder interfaces.
+
+
+9.04 2009-05-30
+-------------------------
+- LZMA2 compression method support
+- xz format support
+
+
+4.65 2009-02-03
+-------------------------
+- Some minor fixes
+
+
+4.63 2008-12-31
+-------------------------
+- Some minor fixes
+
+
+4.61 beta 2008-11-23
+-------------------------
+- The bug in ANSI-C LZMA Decoder was fixed:
+ If encoded stream was corrupted, decoder could access memory
+ outside of allocated range.
+- Some changes in ANSI-C 7z Decoder interfaces.
+- LZMA SDK is placed in the public domain.
+
+
+4.60 beta 2008-08-19
+-------------------------
+- Some minor fixes.
+
+
+4.59 beta 2008-08-13
+-------------------------
+- The bug was fixed:
+ LZMA Encoder in fast compression mode could access memory outside of
+ allocated range in some rare cases.
+
+
+4.58 beta 2008-05-05
+-------------------------
+- ANSI-C LZMA Decoder was rewritten for speed optimizations.
+- ANSI-C LZMA Encoder was included to LZMA SDK.
+- C++ LZMA code now is just wrapper over ANSI-C code.
+
+
+4.57 2007-12-12
+-------------------------
+- Speed optimizations in Ñ++ LZMA Decoder.
+- Small changes for more compatibility with some C/C++ compilers.
+
+
+4.49 beta 2007-07-05
+-------------------------
+- .7z ANSI-C Decoder:
+ - now it supports BCJ and BCJ2 filters
+ - now it supports files larger than 4 GB.
+ - now it supports "Last Write Time" field for files.
+- C++ code for .7z archives compressing/decompressing from 7-zip
+ was included to LZMA SDK.
+
+
+4.43 2006-06-04
+-------------------------
+- Small changes for more compatibility with some C/C++ compilers.
+
+
+4.42 2006-05-15
+-------------------------
+- Small changes in .h files in ANSI-C version.
+
+
+4.39 beta 2006-04-14
+-------------------------
+- The bug in versions 4.33b:4.38b was fixed:
+ C++ version of LZMA encoder could not correctly compress
+ files larger than 2 GB with HC4 match finder (-mfhc4).
+
+
+4.37 beta 2005-04-06
+-------------------------
+- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined.
+
+
+4.35 beta 2005-03-02
+-------------------------
+- The bug was fixed in C++ version of LZMA Decoder:
+ If encoded stream was corrupted, decoder could access memory
+ outside of allocated range.
+
+
+4.34 beta 2006-02-27
+-------------------------
+- Compressing speed and memory requirements for compressing were increased
+- LZMA now can use only these match finders: HC4, BT2, BT3, BT4
+
+
+4.32 2005-12-09
+-------------------------
+- Java version of LZMA SDK was included
+
+
+4.30 2005-11-20
+-------------------------
+- Compression ratio was improved in -a2 mode
+- Speed optimizations for compressing in -a2 mode
+- -fb switch now supports values up to 273
+- The bug in 7z_C (7zIn.c) was fixed:
+ It used Alloc/Free functions from different memory pools.
+ So if program used two memory pools, it worked incorrectly.
+- 7z_C: .7z format supporting was improved
+- LZMA# SDK (C#.NET version) was included
+
+
+4.27 (Updated) 2005-09-21
+-------------------------
+- Some GUIDs/interfaces in C++ were changed.
+ IStream.h:
+ ISequentialInStream::Read now works as old ReadPart
+ ISequentialOutStream::Write now works as old WritePart
+
+
+4.27 2005-08-07
+-------------------------
+- The bug in LzmaDecodeSize.c was fixed:
+ if _LZMA_IN_CB and _LZMA_OUT_READ were defined,
+ decompressing worked incorrectly.
+
+
+4.26 2005-08-05
+-------------------------
+- Fixes in 7z_C code and LzmaTest.c:
+ previous versions could work incorrectly,
+ if malloc(0) returns 0
+
+
+4.23 2005-06-29
+-------------------------
+- Small fixes in C++ code
+
+
+4.22 2005-06-10
+-------------------------
+- Small fixes
+
+
+4.21 2005-06-08
+-------------------------
+- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed
+- New additional version of ANSI-C LZMA Decoder with zlib-like interface:
+ - LzmaStateDecode.h
+ - LzmaStateDecode.c
+ - LzmaStateTest.c
+- ANSI-C LZMA Decoder now can decompress files larger than 4 GB
+
+
+4.17 2005-04-18
+-------------------------
+- New example for RAM->RAM compressing/decompressing:
+ LZMA + BCJ (filter for x86 code):
+ - LzmaRam.h
+ - LzmaRam.cpp
+ - LzmaRamDecode.h
+ - LzmaRamDecode.c
+ - -f86 switch for lzma.exe
+
+
+4.16 2005-03-29
+-------------------------
+- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder):
+ If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,
+ decoder could access memory outside of allocated range.
+- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).
+ Old version of LZMA Decoder now is in file LzmaDecodeSize.c.
+ LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c
+- Small speed optimization in LZMA C++ code
+- filter for SPARC's code was added
+- Simplified version of .7z ANSI-C Decoder was included
+
+
+4.06 2004-09-05
+-------------------------
+- The bug in v4.05 was fixed:
+ LZMA-Encoder didn't release output stream in some cases.
+
+
+4.05 2004-08-25
+-------------------------
+- Source code of filters for x86, IA-64, ARM, ARM-Thumb
+ and PowerPC code was included to SDK
+- Some internal minor changes
+
+
+4.04 2004-07-28
+-------------------------
+- More compatibility with some C++ compilers
+
+
+4.03 2004-06-18
+-------------------------
+- "Benchmark" command was added. It measures compressing
+ and decompressing speed and shows rating values.
+ Also it checks hardware errors.
+
+
+4.02 2004-06-10
+-------------------------
+- C++ LZMA Encoder/Decoder code now is more portable
+ and it can be compiled by GCC on Linux.
+
+
+4.01 2004-02-15
+-------------------------
+- Some detection of data corruption was enabled.
+ LzmaDecode.c / RangeDecoderReadByte
+ .....
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+
+
+4.00 2004-02-13
+-------------------------
+- Original version of LZMA SDK
+
+
+
+HISTORY of the LZMA
+-------------------
+ 2001-2008: Improvements to LZMA compressing/decompressing code,
+ keeping compatibility with original LZMA format
+ 1996-2001: Development of LZMA compression format
+
+ Some milestones:
+
+ 2001-08-30: LZMA compression was added to 7-Zip
+ 1999-01-02: First version of 7-Zip was released
+
+
+End of document
diff --git a/lib/lzma/import_lzmasdk.sh b/lib/lzma/import_lzmasdk.sh
new file mode 100644
index 00000000..1e0f6863
--- /dev/null
+++ b/lib/lzma/import_lzmasdk.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+usage() {
+ echo "Usage: $0 lzmaVERSION.tar.bz2" >&2
+ echo >&2
+ exit 1
+}
+
+if [ "$1" = "" ] ; then
+ usage
+fi
+
+if [ ! -f $1 ] ; then
+ echo "$1 doesn't exist!" >&2
+ exit 1
+fi
+
+BASENAME=`basename $1 .tar.bz2`
+TMPDIR=/tmp/tmp_lib_$BASENAME
+FILES="C/LzmaDec.h
+ C/Types.h
+ C/LzmaDec.c
+ history.txt
+ lzma.txt"
+
+mkdir -p $TMPDIR
+echo "Untar $1 -> $TMPDIR"
+tar -jxf $1 -C $TMPDIR
+
+for i in $FILES; do
+ echo Copying $TMPDIR/$i \-\> `basename $i`
+ cp $TMPDIR/$i .
+ chmod -x `basename $i`
+done
+
+echo "done!"
diff --git a/lib/lzma/license.txt b/lib/lzma/license.txt
new file mode 100644
index 00000000..48b9820c
--- /dev/null
+++ b/lib/lzma/license.txt
@@ -0,0 +1,3 @@
+ License
+
+LZMA SDK is placed in the public domain.
diff --git a/lib/lzma/lzma.txt b/lib/lzma/lzma.txt
new file mode 100644
index 00000000..144cd9ae
--- /dev/null
+++ b/lib/lzma/lzma.txt
@@ -0,0 +1,598 @@
+LZMA SDK 9.20
+-------------
+
+LZMA SDK provides the documentation, samples, header files, libraries,
+and tools you need to develop applications that use LZMA compression.
+
+LZMA is default and general compression method of 7z format
+in 7-Zip compression program (www.7-zip.org). LZMA provides high
+compression ratio and very fast decompression.
+
+LZMA is an improved version of famous LZ77 compression algorithm.
+It was improved in way of maximum increasing of compression ratio,
+keeping high decompression speed and low memory requirements for
+decompressing.
+
+
+
+LICENSE
+-------
+
+LZMA SDK is written and placed in the public domain by Igor Pavlov.
+
+Some code in LZMA SDK is based on public domain code from another developers:
+ 1) PPMd var.H (2001): Dmitry Shkarin
+ 2) SHA-256: Wei Dai (Crypto++ library)
+
+
+LZMA SDK Contents
+-----------------
+
+LZMA SDK includes:
+
+ - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
+ - Compiled file->file LZMA compressing/decompressing program for Windows system
+
+
+UNIX/Linux version
+------------------
+To compile C++ version of file->file LZMA encoding, go to directory
+CPP/7zip/Bundles/LzmaCon
+and call make to recompile it:
+ make -f makefile.gcc clean all
+
+In some UNIX/Linux versions you must compile LZMA with static libraries.
+To compile with static libraries, you can use
+LIB = -lm -static
+
+
+Files
+---------------------
+lzma.txt - LZMA SDK description (this file)
+7zFormat.txt - 7z Format description
+7zC.txt - 7z ANSI-C Decoder description
+methods.txt - Compression method IDs for .7z
+lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
+7zr.exe - 7-Zip with 7z/lzma/xz support.
+history.txt - history of the LZMA SDK
+
+
+Source code structure
+---------------------
+
+C/ - C files
+ 7zCrc*.* - CRC code
+ Alloc.* - Memory allocation functions
+ Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
+ LzFind.* - Match finder for LZ (LZMA) encoders
+ LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
+ LzHash.h - Additional file for LZ match finder
+ LzmaDec.* - LZMA decoding
+ LzmaEnc.* - LZMA encoding
+ LzmaLib.* - LZMA Library for DLL calling
+ Types.h - Basic types for another .c files
+ Threads.* - The code for multithreading.
+
+ LzmaLib - LZMA Library (.DLL for Windows)
+
+ LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
+
+ Archive - files related to archiving
+ 7z - 7z ANSI-C Decoder
+
+CPP/ -- CPP files
+
+ Common - common files for C++ projects
+ Windows - common files for Windows related code
+
+ 7zip - files related to 7-Zip Project
+
+ Common - common files for 7-Zip
+
+ Compress - files related to compression/decompression
+
+ Archive - files related to archiving
+
+ Common - common files for archive handling
+ 7z - 7z C++ Encoder/Decoder
+
+ Bundles - Modules that are bundles of other modules
+
+ Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
+ LzmaCon - lzma.exe: LZMA compression/decompression
+ Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
+ Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
+
+ UI - User Interface files
+
+ Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
+ Common - Common UI files
+ Console - Code for console archiver
+
+
+
+CS/ - C# files
+ 7zip
+ Common - some common files for 7-Zip
+ Compress - files related to compression/decompression
+ LZ - files related to LZ (Lempel-Ziv) compression algorithm
+ LZMA - LZMA compression/decompression
+ LzmaAlone - file->file LZMA compression/decompression
+ RangeCoder - Range Coder (special code of compression/decompression)
+
+Java/ - Java files
+ SevenZip
+ Compression - files related to compression/decompression
+ LZ - files related to LZ (Lempel-Ziv) compression algorithm
+ LZMA - LZMA compression/decompression
+ RangeCoder - Range Coder (special code of compression/decompression)
+
+
+C/C++ source code of LZMA SDK is part of 7-Zip project.
+7-Zip source code can be downloaded from 7-Zip's SourceForge page:
+
+ http://sourceforge.net/projects/sevenzip/
+
+
+
+LZMA features
+-------------
+ - Variable dictionary size (up to 1 GB)
+ - Estimated compressing speed: about 2 MB/s on 2 GHz CPU
+ - Estimated decompressing speed:
+ - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
+ - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
+ - Small memory requirements for decompressing (16 KB + DictionarySize)
+ - Small code size for decompressing: 5-8 KB
+
+LZMA decoder uses only integer operations and can be
+implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
+
+Some critical operations that affect the speed of LZMA decompression:
+ 1) 32*16 bit integer multiply
+ 2) Misspredicted branches (penalty mostly depends from pipeline length)
+ 3) 32-bit shift and arithmetic operations
+
+The speed of LZMA decompressing mostly depends from CPU speed.
+Memory speed has no big meaning. But if your CPU has small data cache,
+overall weight of memory speed will slightly increase.
+
+
+How To Use
+----------
+
+Using LZMA encoder/decoder executable
+--------------------------------------
+
+Usage: LZMA <e|d> inputFile outputFile [<switches>...]
+
+ e: encode file
+
+ d: decode file
+
+ b: Benchmark. There are two tests: compressing and decompressing
+ with LZMA method. Benchmark shows rating in MIPS (million
+ instructions per second). Rating value is calculated from
+ measured speed and it is normalized with Intel's Core 2 results.
+ Also Benchmark checks possible hardware errors (RAM
+ errors in most cases). Benchmark uses these settings:
+ (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter.
+ Also you can change the number of iterations. Example for 30 iterations:
+ LZMA b 30
+ Default number of iterations is 10.
+
+<Switches>
+
+
+ -a{N}: set compression mode 0 = fast, 1 = normal
+ default: 1 (normal)
+
+ d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB)
+ The maximum value for dictionary size is 1 GB = 2^30 bytes.
+ Dictionary size is calculated as DictionarySize = 2^N bytes.
+ For decompressing file compressed by LZMA method with dictionary
+ size D = 2^N you need about D bytes of memory (RAM).
+
+ -fb{N}: set number of fast bytes - [5, 273], default: 128
+ Usually big number gives a little bit better compression ratio
+ and slower compression process.
+
+ -lc{N}: set number of literal context bits - [0, 8], default: 3
+ Sometimes lc=4 gives gain for big files.
+
+ -lp{N}: set number of literal pos bits - [0, 4], default: 0
+ lp switch is intended for periodical data when period is
+ equal 2^N. For example, for 32-bit (4 bytes)
+ periodical data you can use lp=2. Often it's better to set lc0,
+ if you change lp switch.
+
+ -pb{N}: set number of pos bits - [0, 4], default: 2
+ pb switch is intended for periodical data
+ when period is equal 2^N.
+
+ -mf{MF_ID}: set Match Finder. Default: bt4.
+ Algorithms from hc* group doesn't provide good compression
+ ratio, but they often works pretty fast in combination with
+ fast mode (-a0).
+
+ Memory requirements depend from dictionary size
+ (parameter "d" in table below).
+
+ MF_ID Memory Description
+
+ bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing.
+ bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing.
+ bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing.
+ hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing.
+
+ -eos: write End Of Stream marker. By default LZMA doesn't write
+ eos marker, since LZMA decoder knows uncompressed size
+ stored in .lzma file header.
+
+ -si: Read data from stdin (it will write End Of Stream marker).
+ -so: Write data to stdout
+
+
+Examples:
+
+1) LZMA e file.bin file.lzma -d16 -lc0
+
+compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)
+and 0 literal context bits. -lc0 allows to reduce memory requirements
+for decompression.
+
+
+2) LZMA e file.bin file.lzma -lc0 -lp2
+
+compresses file.bin to file.lzma with settings suitable
+for 32-bit periodical data (for example, ARM or MIPS code).
+
+3) LZMA d file.lzma file.bin
+
+decompresses file.lzma to file.bin.
+
+
+Compression ratio hints
+-----------------------
+
+Recommendations
+---------------
+
+To increase the compression ratio for LZMA compressing it's desirable
+to have aligned data (if it's possible) and also it's desirable to locate
+data in such order, where code is grouped in one place and data is
+grouped in other place (it's better than such mixing: code, data, code,
+data, ...).
+
+
+Filters
+-------
+You can increase the compression ratio for some data types, using
+special filters before compressing. For example, it's possible to
+increase the compression ratio on 5-10% for code for those CPU ISAs:
+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
+
+You can find C source code of such filters in C/Bra*.* files
+
+You can check the compression ratio gain of these filters with such
+7-Zip commands (example for ARM code):
+No filter:
+ 7z a a1.7z a.bin -m0=lzma
+
+With filter for little-endian ARM code:
+ 7z a a2.7z a.bin -m0=arm -m1=lzma
+
+It works in such manner:
+Compressing = Filter_encoding + LZMA_encoding
+Decompressing = LZMA_decoding + Filter_decoding
+
+Compressing and decompressing speed of such filters is very high,
+so it will not increase decompressing time too much.
+Moreover, it reduces decompression time for LZMA_decoding,
+since compression ratio with filtering is higher.
+
+These filters convert CALL (calling procedure) instructions
+from relative offsets to absolute addresses, so such data becomes more
+compressible.
+
+For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
+
+
+LZMA compressed file format
+---------------------------
+Offset Size Description
+ 0 1 Special LZMA properties (lc,lp, pb in encoded form)
+ 1 4 Dictionary size (little endian)
+ 5 8 Uncompressed size (little endian). -1 means unknown size
+ 13 Compressed data
+
+
+ANSI-C LZMA Decoder
+~~~~~~~~~~~~~~~~~~~
+
+Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
+If you want to use old interfaces you can download previous version of LZMA SDK
+from sourceforge.net site.
+
+To use ANSI-C LZMA Decoder you need the following files:
+1) LzmaDec.h + LzmaDec.c + Types.h
+LzmaUtil/LzmaUtil.c is example application that uses these files.
+
+
+Memory requirements for LZMA decoding
+-------------------------------------
+
+Stack usage of LZMA decoding function for local variables is not
+larger than 200-400 bytes.
+
+LZMA Decoder uses dictionary buffer and internal state structure.
+Internal state structure consumes
+ state_size = (4 + (1.5 << (lc + lp))) KB
+by default (lc=3, lp=0), state_size = 16 KB.
+
+
+How To decompress data
+----------------------
+
+LZMA Decoder (ANSI-C version) now supports 2 interfaces:
+1) Single-call Decompressing
+2) Multi-call State Decompressing (zlib-like interface)
+
+You must use external allocator:
+Example:
+void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
+void SzFree(void *p, void *address) { p = p; free(address); }
+ISzAlloc alloc = { SzAlloc, SzFree };
+
+You can use p = p; operator to disable compiler warnings.
+
+
+Single-call Decompressing
+-------------------------
+When to use: RAM->RAM decompressing
+Compile files: LzmaDec.h + LzmaDec.c + Types.h
+Compile defines: no defines
+Memory Requirements:
+ - Input buffer: compressed size
+ - Output buffer: uncompressed size
+ - LZMA Internal Structures: state_size (16 KB for default settings)
+
+Interface:
+ int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc);
+ In:
+ dest - output data
+ destLen - output data size
+ src - input data
+ srcLen - input data size
+ propData - LZMA properties (5 bytes)
+ propSize - size of propData buffer (5 bytes)
+ finishMode - It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+ You can use LZMA_FINISH_END, when you know that
+ current output buffer covers last bytes of stream.
+ alloc - Memory allocator.
+
+ Out:
+ destLen - processed output size
+ srcLen - processed input size
+
+ Output:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+
+ If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
+ and output value of destLen will be less than output buffer size limit.
+
+ You can use multiple checks to test data integrity after full decompression:
+ 1) Check Result and "status" variable.
+ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+ You must use correct finish mode in that case. */
+
+
+Multi-call State Decompressing (zlib-like interface)
+----------------------------------------------------
+
+When to use: file->file decompressing
+Compile files: LzmaDec.h + LzmaDec.c + Types.h
+
+Memory Requirements:
+ - Buffer for input stream: any size (for example, 16 KB)
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures: state_size (16 KB for default settings)
+ - LZMA dictionary (dictionary size is encoded in LZMA properties header)
+
+1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
+ unsigned char header[LZMA_PROPS_SIZE + 8];
+ ReadFile(inFile, header, sizeof(header)
+
+2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
+
+ CLzmaDec state;
+ LzmaDec_Constr(&state);
+ res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
+ if (res != SZ_OK)
+ return res;
+
+3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
+
+ LzmaDec_Init(&state);
+ for (;;)
+ {
+ ...
+ int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
+ ...
+ }
+
+
+4) Free all allocated structures
+ LzmaDec_Free(&state, &g_Alloc);
+
+For full code example, look at C/LzmaUtil/LzmaUtil.c code.
+
+
+How To compress data
+--------------------
+
+Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
+LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
+
+Memory Requirements:
+ - (dictSize * 11.5 + 6 MB) + state_size
+
+Lzma Encoder can use two memory allocators:
+1) alloc - for small arrays.
+2) allocBig - for big arrays.
+
+For example, you can use Large RAM Pages (2 MB) in allocBig allocator for
+better compression speed. Note that Windows has bad implementation for
+Large RAM Pages.
+It's OK to use same allocator for alloc and allocBig.
+
+
+Single-call Compression with callbacks
+--------------------------------------
+
+Check C/LzmaUtil/LzmaUtil.c as example,
+
+When to use: file->file decompressing
+
+1) you must implement callback structures for interfaces:
+ISeqInStream
+ISeqOutStream
+ICompressProgress
+ISzAlloc
+
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
+static void SzFree(void *p, void *address) { p = p; MyFree(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+ CFileSeqInStream inStream;
+ CFileSeqOutStream outStream;
+
+ inStream.funcTable.Read = MyRead;
+ inStream.file = inFile;
+ outStream.funcTable.Write = MyWrite;
+ outStream.file = outFile;
+
+
+2) Create CLzmaEncHandle object;
+
+ CLzmaEncHandle enc;
+
+ enc = LzmaEnc_Create(&g_Alloc);
+ if (enc == 0)
+ return SZ_ERROR_MEM;
+
+
+3) initialize CLzmaEncProps properties;
+
+ LzmaEncProps_Init(&props);
+
+ Then you can change some properties in that structure.
+
+4) Send LZMA properties to LZMA Encoder
+
+ res = LzmaEnc_SetProps(enc, &props);
+
+5) Write encoded properties to header
+
+ Byte header[LZMA_PROPS_SIZE + 8];
+ size_t headerSize = LZMA_PROPS_SIZE;
+ UInt64 fileSize;
+ int i;
+
+ res = LzmaEnc_WriteProperties(enc, header, &headerSize);
+ fileSize = MyGetFileLength(inFile);
+ for (i = 0; i < 8; i++)
+ header[headerSize++] = (Byte)(fileSize >> (8 * i));
+ MyWriteFileAndCheck(outFile, header, headerSize)
+
+6) Call encoding function:
+ res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
+ NULL, &g_Alloc, &g_Alloc);
+
+7) Destroy LZMA Encoder Object
+ LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
+
+
+If callback function return some error code, LzmaEnc_Encode also returns that code
+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
+
+
+Single-call RAM->RAM Compression
+--------------------------------
+
+Single-call RAM->RAM Compression is similar to Compression with callbacks,
+but you provide pointers to buffers instead of pointers to stream callbacks:
+
+HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+Return code:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_PARAM - Incorrect paramater
+ SZ_ERROR_OUTPUT_EOF - output buffer overflow
+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+
+
+
+Defines
+-------
+
+_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
+
+_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for
+ some structures will be doubled in that case.
+
+_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit.
+
+_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
+
+
+_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.
+
+
+C++ LZMA Encoder/Decoder
+~~~~~~~~~~~~~~~~~~~~~~~~
+C++ LZMA code use COM-like interfaces. So if you want to use it,
+you can study basics of COM/OLE.
+C++ LZMA code is just wrapper over ANSI-C code.
+
+
+C++ Notes
+~~~~~~~~~~~~~~~~~~~~~~~~
+If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
+you must check that you correctly work with "new" operator.
+7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
+So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
+operator new(size_t size)
+{
+ void *p = ::malloc(size);
+ if (p == 0)
+ throw CNewException();
+ return p;
+}
+If you use MSCV that throws exception for "new" operator, you can compile without
+"NewHandler.cpp". So standard exception will be used. Actually some code of
+7-Zip catches any exception in internal code and converts it to HRESULT code.
+So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/sdk.html
+http://www.7-zip.org/support.html
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
new file mode 100644
index 00000000..45612a83
--- /dev/null
+++ b/lib/lzo/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2008
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+
+obj-y += lzo1x_decompress.o
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
new file mode 100644
index 00000000..65fef0b0
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress.c
@@ -0,0 +1,359 @@
+/*
+ * LZO1X Decompressor from MiniLZO
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <common.h>
+#include <linux/lzo.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
+#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
+#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+
+static const unsigned char lzop_magic[] = {
+ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
+};
+
+#define HEADER_HAS_FILTER 0x00000800L
+
+
+bool lzop_is_valid_header(const unsigned char *src)
+{
+ int i;
+ /* read magic: 9 first bytes */
+ for (i = 0; i < ARRAY_SIZE(lzop_magic); i++) {
+ if (*src++ != lzop_magic[i])
+ return false;
+ }
+ return true;
+}
+
+static inline const unsigned char *parse_header(const unsigned char *src)
+{
+ u16 version;
+ int i;
+
+ if (!lzop_is_valid_header(src))
+ return NULL;
+
+ /* skip header */
+ src += 9;
+
+ /* get version (2bytes), skip library version (2),
+ * 'need to be extracted' version (2) and
+ * method (1) */
+ version = get_unaligned_be16(src);
+ src += 7;
+ if (version >= 0x0940)
+ src++;
+ if (get_unaligned_be32(src) & HEADER_HAS_FILTER)
+ src += 4; /* filter info */
+
+ /* skip flags, mode and mtime_low */
+ src += 12;
+ if (version >= 0x0940)
+ src += 4; /* skip mtime_high */
+
+ i = *src++;
+ /* don't care about the file name, and skip checksum */
+ src += i + 4;
+
+ return src;
+}
+
+int lzop_decompress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len)
+{
+ unsigned char *start = dst;
+ const unsigned char *send = src + src_len;
+ u32 slen, dlen;
+ size_t tmp, remaining;
+ int r;
+
+ src = parse_header(src);
+ if (!src)
+ return LZO_E_ERROR;
+
+ remaining = *dst_len;
+ while (src < send) {
+ /* read uncompressed block size */
+ dlen = get_unaligned_be32(src);
+ src += 4;
+
+ /* exit if last block */
+ if (dlen == 0) {
+ *dst_len = dst - start;
+ return LZO_E_OK;
+ }
+
+ /* read compressed block size, and skip block checksum info */
+ slen = get_unaligned_be32(src);
+ src += 8;
+
+ if (slen <= 0 || slen > dlen)
+ return LZO_E_ERROR;
+
+ /* abort if buffer ran out of room */
+ if (dlen > remaining)
+ return LZO_E_OUTPUT_OVERRUN;
+
+ /* When the input data is not compressed at all,
+ * lzo1x_decompress_safe will fail, so call memcpy()
+ * instead */
+ if (dlen == slen) {
+ memcpy(dst, src, slen);
+ } else {
+ /* decompress */
+ tmp = dlen;
+ r = lzo1x_decompress_safe((u8 *)src, slen, dst, &tmp);
+
+ if (r != LZO_E_OK) {
+ *dst_len = dst - start;
+ return r;
+ }
+
+ if (dlen != tmp)
+ return LZO_E_ERROR;
+ }
+
+ src += slen;
+ dst += dlen;
+ remaining -= dlen;
+ }
+
+ return LZO_E_INPUT_OVERRUN;
+}
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+ const unsigned char *ip = in, *m_pos;
+ unsigned char *op = out;
+ size_t t;
+
+ *out_len = 0;
+
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while ((ip < ip_end)) {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 15 + *ip++;
+ }
+ if (HAVE_OP(t + 3, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 4, ip_end, ip))
+ goto input_overrun;
+
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ if (--t > 0) {
+ if (t >= 4) {
+ do {
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0) {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ } else {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ }
+
+first_literal_run:
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+
+ if (HAVE_OP(3, op_end, op))
+ goto output_overrun;
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+
+ goto match_done;
+
+ do {
+match:
+ if (t >= 64) {
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+ goto copy_match;
+ } else if (t >= 32) {
+ t &= 31;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 31 + *ip++;
+ }
+ m_pos = op - 1;
+ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ } else if (t >= 16) {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+
+ t &= 7;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 7 + *ip++;
+ }
+ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ } else {
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(2, op_end, op))
+ goto output_overrun;
+
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+ goto match_done;
+ }
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4 - (3 - 1);
+ do {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0)
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ } else {
+copy_match:
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ }
+match_done:
+ t = ip[-2] & 3;
+ if (t == 0)
+ break;
+match_next:
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+
+ *op++ = *ip++;
+ if (t > 1) {
+ *op++ = *ip++;
+ if (t > 2)
+ *op++ = *ip++;
+ }
+
+ t = *ip++;
+ } while (ip < ip_end);
+ }
+
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+ *out_len = op - out;
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
new file mode 100644
index 00000000..b6d482c4
--- /dev/null
+++ b/lib/lzo/lzodefs.h
@@ -0,0 +1,43 @@
+/*
+ * lzodefs.h -- architecture, OS and compiler specific defines
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO_VERSION 0x2020
+#define LZO_VERSION_STRING "2.02"
+#define LZO_VERSION_DATE "Oct 17 2005"
+
+#define M1_MAX_OFFSET 0x0400
+#define M2_MAX_OFFSET 0x0800
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#define M2_MAX_LEN 8
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+#define D_BITS 14
+#define D_MASK ((1u << D_BITS) - 1)
+#define D_HIGH ((D_MASK >> 1) + 1)
+
+#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
+ << (s1)) ^ (p)[0])
+#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/lib/md5.c b/lib/md5.c
new file mode 100644
index 00000000..2ae4a063
--- /dev/null
+++ b/lib/md5.c
@@ -0,0 +1,314 @@
+/*
+ * This file was transplanted with slight modifications from Linux sources
+ * (fs/cifs/md5.c) into U-Boot by Bartlomiej Sieka <tur@semihalf.com>.
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code slightly modified to fit into Samba by
+ abartlet@samba.org Jun 2001
+ and to fit the cifs vfs by
+ Steve French sfrench@us.ibm.com */
+
+#include "compiler.h"
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <watchdog.h>
+#endif /* USE_HOSTCC */
+#include <u-boot/md5.h>
+
+static void
+MD5Transform(__u32 buf[4], __u32 const in[16]);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void
+byteReverse(unsigned char *buf, unsigned longs)
+{
+ __u32 t;
+ do {
+ t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(__u32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+static void
+MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+static void
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ register __u32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memmove(p, buf, len);
+ return;
+ }
+ memmove(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memmove(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memmove(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+static void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in32[14] = ctx->bits[0];
+ ctx->in32[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memmove(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(__u32 buf[4], __u32 const in[16])
+{
+ register __u32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ * Calculate and store in 'output' the MD5 digest of 'len' bytes at
+ * 'input'. 'output' must have enough space to hold 16 bytes.
+ */
+void
+md5 (unsigned char *input, int len, unsigned char output[16])
+{
+ struct MD5Context context;
+
+ MD5Init(&context);
+ MD5Update(&context, input, len);
+ MD5Final(output, &context);
+}
+
+
+/*
+ * Calculate and store in 'output' the MD5 digest of 'len' bytes at 'input'.
+ * 'output' must have enough space to hold 16 bytes. If 'chunk' Trigger the
+ * watchdog every 'chunk_sz' bytes of input processed.
+ */
+void
+md5_wd (unsigned char *input, int len, unsigned char output[16],
+ unsigned int chunk_sz)
+{
+ struct MD5Context context;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ unsigned char *end, *curr;
+ int chunk;
+#endif
+
+ MD5Init(&context);
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ curr = input;
+ end = input + len;
+ while (curr < end) {
+ chunk = end - curr;
+ if (chunk > chunk_sz)
+ chunk = chunk_sz;
+ MD5Update(&context, curr, chunk);
+ curr += chunk;
+ WATCHDOG_RESET ();
+ }
+#else
+ MD5Update(&context, input, len);
+#endif
+
+ MD5Final(output, &context);
+}
diff --git a/lib/membuff.c b/lib/membuff.c
new file mode 100644
index 00000000..45dae2d5
--- /dev/null
+++ b/lib/membuff.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Copyright (c) 1992 Simon Glass
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include "membuff.h"
+
+void membuff_purge(struct membuff *mb)
+{
+ /* set mb->head and mb->tail so the buffers look empty */
+ mb->head = mb->start;
+ mb->tail = mb->start;
+}
+
+static int membuff_putrawflex(struct membuff *mb, int maxlen, bool update,
+ char ***data, int *offsetp)
+{
+ int len;
+
+ /* always write to 'mb->head' */
+ assert(data && offsetp);
+ *data = &mb->start;
+ *offsetp = mb->head - mb->start;
+
+ /* if there is no buffer, we can do nothing */
+ if (!mb->start)
+ return 0;
+
+ /*
+ * if head is ahead of tail, we can write from head until the end of
+ * the buffer
+ */
+ if (mb->head >= mb->tail) {
+ /* work out how many bytes can fit here */
+ len = mb->end - mb->head - 1;
+ if (maxlen >= 0 && len > maxlen)
+ len = maxlen;
+
+ /* update the head pointer to mark these bytes as written */
+ if (update)
+ mb->head += len;
+
+ /*
+ * if the tail isn't at start of the buffer, then we can
+ * write one more byte right at the end
+ */
+ if ((maxlen < 0 || len < maxlen) && mb->tail != mb->start) {
+ len++;
+ if (update)
+ mb->head = mb->start;
+ }
+
+ /* otherwise now we can write until head almost reaches tail */
+ } else {
+ /* work out how many bytes can fit here */
+ len = mb->tail - mb->head - 1;
+ if (maxlen >= 0 && len > maxlen)
+ len = maxlen;
+
+ /* update the head pointer to mark these bytes as written */
+ if (update)
+ mb->head += len;
+ }
+
+ /* return the number of bytes which can be/must be written */
+ return len;
+}
+
+int membuff_putraw(struct membuff *mb, int maxlen, bool update, char **data)
+{
+ char **datap;
+ int offset;
+ int size;
+
+ size = membuff_putrawflex(mb, maxlen, update, &datap, &offset);
+ *data = *datap + offset;
+
+ return size;
+}
+
+bool membuff_putbyte(struct membuff *mb, int ch)
+{
+ char *data;
+
+ if (membuff_putraw(mb, 1, true, &data) != 1)
+ return false;
+ *data = ch;
+
+ return true;
+}
+
+int membuff_getraw(struct membuff *mb, int maxlen, bool update, char **data)
+{
+ int len;
+
+ /* assume for now there is no data to get */
+ len = 0;
+
+ /*
+ * in this case head is ahead of tail, so we must return data between
+ *'tail' and 'head'
+ */
+ if (mb->head > mb->tail) {
+ /* work out the amount of data */
+ *data = mb->tail;
+ len = mb->head - mb->tail;
+
+ /* check it isn't too much */
+ if (maxlen >= 0 && len > maxlen)
+ len = maxlen;
+
+ /* & mark it as read from the buffer */
+ if (update)
+ mb->tail += len;
+ }
+
+ /*
+ * if head is before tail, then we have data between 'tail' and 'end'
+ * and some more data between 'start' and 'head'(which we can't
+ * return this time
+ */
+ else if (mb->head < mb->tail) {
+ /* work out the amount of data */
+ *data = mb->tail;
+ len = mb->end - mb->tail;
+ if (maxlen >= 0 && len > maxlen)
+ len = maxlen;
+ if (update) {
+ mb->tail += len;
+ if (mb->tail == mb->end)
+ mb->tail = mb->start;
+ }
+ }
+
+ debug("getraw: maxlen=%d, update=%d, head=%d, tail=%d, data=%d, len=%d",
+ maxlen, update, (int)(mb->head - mb->start),
+ (int)(mb->tail - mb->start), (int)(*data - mb->start), len);
+
+ /* return the number of bytes we found */
+ return len;
+}
+
+int membuff_getbyte(struct membuff *mb)
+{
+ char *data = 0;
+
+ return membuff_getraw(mb, 1, true, &data) != 1 ? -1 : *(uint8_t *)data;
+}
+
+int membuff_peekbyte(struct membuff *mb)
+{
+ char *data = 0;
+
+ return membuff_getraw(mb, 1, false, &data) != 1 ? -1 : *(uint8_t *)data;
+}
+
+int membuff_get(struct membuff *mb, char *buff, int maxlen)
+{
+ char *data = 0, *buffptr = buff;
+ int len = 1, i;
+
+ /*
+ * do this in up to two lots(see GetRaw for why) stopping when there
+ * is no more data
+ */
+ for (i = 0; len && i < 2; i++) {
+ /* get a pointer to the data available */
+ len = membuff_getraw(mb, maxlen, true, &data);
+
+ /* copy it into the buffer */
+ memcpy(buffptr, data, len);
+ buffptr += len;
+ maxlen -= len;
+ }
+
+ /* return the number of bytes read */
+ return buffptr - buff;
+}
+
+int membuff_put(struct membuff *mb, const char *buff, int length)
+{
+ char *data;
+ int towrite, i, written;
+
+ for (i = written = 0; i < 2; i++) {
+ /* ask where some data can be written */
+ towrite = membuff_putraw(mb, length, true, &data);
+
+ /* and write it, updating the bytes length */
+ memcpy(data, buff, towrite);
+ written += towrite;
+ buff += towrite;
+ length -= towrite;
+ }
+
+ /* return the number of bytes written */
+ return written;
+}
+
+bool membuff_isempty(struct membuff *mb)
+{
+ return mb->head == mb->tail;
+}
+
+int membuff_avail(struct membuff *mb)
+{
+ struct membuff copy;
+ int i, avail;
+ char *data = 0;
+
+ /* make a copy of this buffer's control data */
+ copy = *mb;
+
+ /* now read everything out of the copied buffer */
+ for (i = avail = 0; i < 2; i++)
+ avail += membuff_getraw(&copy, -1, true, &data);
+
+ /* and return how much we read */
+ return avail;
+}
+
+int membuff_size(struct membuff *mb)
+{
+ return mb->end - mb->start;
+}
+
+bool membuff_makecontig(struct membuff *mb)
+{
+ int topsize, botsize;
+
+ debug("makecontig: head=%d, tail=%d, size=%d",
+ (int)(mb->head - mb->start), (int)(mb->tail - mb->start),
+ (int)(mb->end - mb->start));
+
+ /*
+ * first we move anything at the start of the buffer into the correct
+ * place some way along
+ */
+ if (mb->tail > mb->head) {
+ /*
+ * the data is split into two parts, from 0 to ->head and
+ * from ->tail to ->end. We move the stuff from 0 to ->head
+ * up to make space for the other data before it
+ */
+ topsize = mb->end - mb->tail;
+ botsize = mb->head - mb->start;
+
+ /*
+ * must move data at bottom up by 'topsize' bytes - check if
+ * there's room
+ */
+ if (mb->head + topsize >= mb->tail)
+ return false;
+ memmove(mb->start + topsize, mb->start, botsize);
+ debug(" - memmove(%d, %d, %d)", topsize, 0, botsize);
+
+ /* nothing at the start, so skip that step */
+ } else {
+ topsize = mb->head - mb->tail;
+ botsize = 0;
+ }
+
+ /* now move data at top down to the bottom */
+ memcpy(mb->start, mb->tail, topsize);
+ debug(" - memcpy(%d, %d, %d)", 0, (int)(mb->tail - mb->start), topsize);
+
+ /* adjust pointers */
+ mb->tail = mb->start;
+ mb->head = mb->start + topsize + botsize;
+
+ debug(" - head=%d, tail=%d", (int)(mb->head - mb->start),
+ (int)(mb->tail - mb->start));
+
+ /* all ok */
+ return true;
+}
+
+int membuff_free(struct membuff *mb)
+{
+ return mb->end == mb->start ? 0 :
+ (mb->end - mb->start) - 1 - membuff_avail(mb);
+}
+
+int membuff_readline(struct membuff *mb, char *str, int maxlen, int minch)
+{
+ int len; /* number of bytes read (!= string length) */
+ char *s, *end;
+ bool ok = false;
+ char *orig = str;
+
+ end = mb->head >= mb->tail ? mb->head : mb->end;
+ for (len = 0, s = mb->tail; s < end && len < maxlen - 1; str++) {
+ *str = *s++;
+ len++;
+ if (*str == '\n' || *str < minch) {
+ ok = true;
+ break;
+ }
+ if (s == end && mb->tail > mb->head) {
+ s = mb->start;
+ end = mb->head;
+ }
+ }
+
+ /* couldn't get the whole string */
+ if (!ok) {
+ if (maxlen)
+ *orig = '\0';
+ return 0;
+ }
+
+ /* terminate the string, update the membuff and return success */
+ *str = '\0';
+ mb->tail = s == mb->end ? mb->start : s;
+
+ return len;
+}
+
+int membuff_extend_by(struct membuff *mb, int by, int max)
+{
+ int oldhead, oldtail;
+ int size, orig;
+ char *ptr;
+
+ /* double the buffer size until it is big enough */
+ assert(by >= 0);
+ for (orig = mb->end - mb->start, size = orig; size < orig + by;)
+ size *= 2;
+ if (max != -1)
+ size = min(size, max);
+ by = size - orig;
+
+ /* if we're already at maximum, give up */
+ if (by <= 0)
+ return -E2BIG;
+
+ oldhead = mb->head - mb->start;
+ oldtail = mb->tail - mb->start;
+ ptr = realloc(mb->start, size);
+ if (!ptr)
+ return -ENOMEM;
+ mb->start = ptr;
+ mb->head = mb->start + oldhead;
+ mb->tail = mb->start + oldtail;
+
+ if (mb->head < mb->tail) {
+ memmove(mb->tail + by, mb->tail, orig - oldtail);
+ mb->tail += by;
+ }
+ mb->end = mb->start + size;
+
+ return 0;
+}
+
+void membuff_init(struct membuff *mb, char *buff, int size)
+{
+ mb->start = buff;
+ mb->end = mb->start + size;
+ membuff_purge(mb);
+}
+
+int membuff_new(struct membuff *mb, int size)
+{
+ mb->start = malloc(size);
+ if (!mb->start)
+ return -ENOMEM;
+
+ membuff_init(mb, mb->start, size);
+ return 0;
+}
+
+void membuff_uninit(struct membuff *mb)
+{
+ mb->end = NULL;
+ mb->start = NULL;
+ membuff_purge(mb);
+}
+
+void membuff_dispose(struct membuff *mb)
+{
+ free(&mb->start);
+ membuff_uninit(mb);
+}
diff --git a/lib/net_utils.c b/lib/net_utils.c
new file mode 100644
index 00000000..ed5044c3
--- /dev/null
+++ b/lib/net_utils.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic network code. Moved from net.c
+ *
+ * Copyright 1994 - 2000 Neil Russell.
+ * Copyright 2000 Roland Borde
+ * Copyright 2000 Paolo Scaffardi
+ * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ * Copyright 2009 Dirk Behme, dirk.behme@googlemail.com
+ */
+
+#include <common.h>
+
+struct in_addr string_to_ip(const char *s)
+{
+ struct in_addr addr;
+ char *e;
+ int i;
+
+ addr.s_addr = 0;
+ if (s == NULL)
+ return addr;
+
+ for (addr.s_addr = 0, i = 0; i < 4; ++i) {
+ ulong val = s ? simple_strtoul(s, &e, 10) : 0;
+ if (val > 255) {
+ addr.s_addr = 0;
+ return addr;
+ }
+ if (i != 3 && *e != '.') {
+ addr.s_addr = 0;
+ return addr;
+ }
+ addr.s_addr <<= 8;
+ addr.s_addr |= (val & 0xFF);
+ if (s) {
+ s = (*e) ? e+1 : e;
+ }
+ }
+
+ addr.s_addr = htonl(addr.s_addr);
+ return addr;
+}
+
+void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
+{
+ char *end;
+ int i;
+
+ if (!enetaddr)
+ return;
+
+ for (i = 0; i < 6; ++i) {
+ enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
+ if (addr)
+ addr = (*end) ? end + 1 : end;
+ }
+}
diff --git a/lib/of_live.c b/lib/of_live.c
new file mode 100644
index 00000000..c49e95e3
--- /dev/null
+++ b/lib/of_live.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
+ * benh@kernel.crashing.org
+ *
+ * Based on parts of drivers/of/fdt.c from Linux v4.9
+ * Modifications for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ */
+
+#include <common.h>
+#include <linux/libfdt.h>
+#include <of_live.h>
+#include <malloc.h>
+#include <dm/of_access.h>
+#include <linux/err.h>
+
+static void *unflatten_dt_alloc(void **mem, unsigned long size,
+ unsigned long align)
+{
+ void *res;
+
+ *mem = PTR_ALIGN(*mem, align);
+ res = *mem;
+ *mem += size;
+
+ return res;
+}
+
+/**
+ * unflatten_dt_node() - Alloc and populate a device_node from the flat tree
+ * @blob: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
+ * @poffset: pointer to node in flat tree
+ * @dad: Parent struct device_node
+ * @nodepp: The device_node tree created by the call
+ * @fpsize: Size of the node path up at t05he current depth.
+ * @dryrun: If true, do not allocate device nodes but still calculate needed
+ * memory size
+ */
+static void *unflatten_dt_node(const void *blob, void *mem, int *poffset,
+ struct device_node *dad,
+ struct device_node **nodepp,
+ unsigned long fpsize, bool dryrun)
+{
+ const __be32 *p;
+ struct device_node *np;
+ struct property *pp, **prev_pp = NULL;
+ const char *pathp;
+ int l;
+ unsigned int allocl;
+ static int depth;
+ int old_depth;
+ int offset;
+ int has_name = 0;
+ int new_format = 0;
+
+ pathp = fdt_get_name(blob, *poffset, &l);
+ if (!pathp)
+ return mem;
+
+ allocl = ++l;
+
+ /*
+ * version 0x10 has a more compact unit name here instead of the full
+ * path. we accumulate the full path size using "fpsize", we'll rebuild
+ * it later. We detect this because the first character of the name is
+ * not '/'.
+ */
+ if ((*pathp) != '/') {
+ new_format = 1;
+ if (fpsize == 0) {
+ /*
+ * root node: special case. fpsize accounts for path
+ * plus terminating zero. root node only has '/', so
+ * fpsize should be 2, but we want to avoid the first
+ * level nodes to have two '/' so we use fpsize 1 here
+ */
+ fpsize = 1;
+ allocl = 2;
+ l = 1;
+ pathp = "";
+ } else {
+ /*
+ * account for '/' and path size minus terminal 0
+ * already in 'l'
+ */
+ fpsize += l;
+ allocl = fpsize;
+ }
+ }
+
+ np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
+ __alignof__(struct device_node));
+ if (!dryrun) {
+ char *fn;
+
+ fn = (char *)np + sizeof(*np);
+ np->full_name = fn;
+ if (new_format) {
+ /* rebuild full path for new format */
+ if (dad && dad->parent) {
+ strcpy(fn, dad->full_name);
+#ifdef DEBUG
+ if ((strlen(fn) + l + 1) != allocl) {
+ debug("%s: p: %d, l: %d, a: %d\n",
+ pathp, (int)strlen(fn), l,
+ allocl);
+ }
+#endif
+ fn += strlen(fn);
+ }
+ *(fn++) = '/';
+ }
+ memcpy(fn, pathp, l);
+
+ prev_pp = &np->properties;
+ if (dad != NULL) {
+ np->parent = dad;
+ np->sibling = dad->child;
+ dad->child = np;
+ }
+ }
+ /* process properties */
+ for (offset = fdt_first_property_offset(blob, *poffset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(blob, offset))) {
+ const char *pname;
+ int sz;
+
+ p = fdt_getprop_by_offset(blob, offset, &pname, &sz);
+ if (!p) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+
+ if (pname == NULL) {
+ debug("Can't find property name in list !\n");
+ break;
+ }
+ if (strcmp(pname, "name") == 0)
+ has_name = 1;
+ pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+ __alignof__(struct property));
+ if (!dryrun) {
+ /*
+ * We accept flattened tree phandles either in
+ * ePAPR-style "phandle" properties, or the
+ * legacy "linux,phandle" properties. If both
+ * appear and have different values, things
+ * will get weird. Don't do that. */
+ if ((strcmp(pname, "phandle") == 0) ||
+ (strcmp(pname, "linux,phandle") == 0)) {
+ if (np->phandle == 0)
+ np->phandle = be32_to_cpup(p);
+ }
+ /*
+ * And we process the "ibm,phandle" property
+ * used in pSeries dynamic device tree
+ * stuff */
+ if (strcmp(pname, "ibm,phandle") == 0)
+ np->phandle = be32_to_cpup(p);
+ pp->name = (char *)pname;
+ pp->length = sz;
+ pp->value = (__be32 *)p;
+ *prev_pp = pp;
+ prev_pp = &pp->next;
+ }
+ }
+ /*
+ * with version 0x10 we may not have the name property, recreate
+ * it here from the unit name if absent
+ */
+ if (!has_name) {
+ const char *p1 = pathp, *ps = pathp, *pa = NULL;
+ int sz;
+
+ while (*p1) {
+ if ((*p1) == '@')
+ pa = p1;
+ if ((*p1) == '/')
+ ps = p1 + 1;
+ p1++;
+ }
+ if (pa < ps)
+ pa = p1;
+ sz = (pa - ps) + 1;
+ pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
+ __alignof__(struct property));
+ if (!dryrun) {
+ pp->name = "name";
+ pp->length = sz;
+ pp->value = pp + 1;
+ *prev_pp = pp;
+ prev_pp = &pp->next;
+ memcpy(pp->value, ps, sz - 1);
+ ((char *)pp->value)[sz - 1] = 0;
+ debug("fixed up name for %s -> %s\n", pathp,
+ (char *)pp->value);
+ }
+ }
+ if (!dryrun) {
+ *prev_pp = NULL;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+
+ if (!np->name)
+ np->name = "<NULL>";
+ if (!np->type)
+ np->type = "<NULL>"; }
+
+ old_depth = depth;
+ *poffset = fdt_next_node(blob, *poffset, &depth);
+ if (depth < 0)
+ depth = 0;
+ while (*poffset > 0 && depth > old_depth) {
+ mem = unflatten_dt_node(blob, mem, poffset, np, NULL,
+ fpsize, dryrun);
+ if (!mem)
+ return NULL;
+ }
+
+ if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) {
+ debug("unflatten: error %d processing FDT\n", *poffset);
+ return NULL;
+ }
+
+ /*
+ * Reverse the child list. Some drivers assumes node order matches .dts
+ * node order
+ */
+ if (!dryrun && np->child) {
+ struct device_node *child = np->child;
+ np->child = NULL;
+ while (child) {
+ struct device_node *next = child->sibling;
+
+ child->sibling = np->child;
+ np->child = child;
+ child = next;
+ }
+ }
+
+ if (nodepp)
+ *nodepp = np;
+
+ return mem;
+}
+
+/**
+ * unflatten_device_tree() - create tree of device_nodes from flat blob
+ *
+ * unflattens a device-tree, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used.
+ * @blob: The blob to expand
+ * @mynodes: The device_node tree created by the call
+ * @return 0 if OK, -ve on error
+ */
+static int unflatten_device_tree(const void *blob,
+ struct device_node **mynodes)
+{
+ unsigned long size;
+ int start;
+ void *mem;
+
+ debug(" -> unflatten_device_tree()\n");
+
+ if (!blob) {
+ debug("No device tree pointer\n");
+ return -EINVAL;
+ }
+
+ debug("Unflattening device tree:\n");
+ debug("magic: %08x\n", fdt_magic(blob));
+ debug("size: %08x\n", fdt_totalsize(blob));
+ debug("version: %08x\n", fdt_version(blob));
+
+ if (fdt_check_header(blob)) {
+ debug("Invalid device tree blob header\n");
+ return -EINVAL;
+ }
+
+ /* First pass, scan for size */
+ start = 0;
+ size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL,
+ 0, true);
+ if (!size)
+ return -EFAULT;
+ size = ALIGN(size, 4);
+
+ debug(" size is %lx, allocating...\n", size);
+
+ /* Allocate memory for the expanded device tree */
+ mem = malloc(size + 4);
+ memset(mem, '\0', size);
+
+ *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
+
+ debug(" unflattening %p...\n", mem);
+
+ /* Second pass, do actual unflattening */
+ start = 0;
+ unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
+ if (be32_to_cpup(mem + size) != 0xdeadbeef) {
+ debug("End of tree marker overwritten: %08x\n",
+ be32_to_cpup(mem + size));
+ return -ENOSPC;
+ }
+
+ debug(" <- unflatten_device_tree()\n");
+
+ return 0;
+}
+
+int of_live_build(const void *fdt_blob, struct device_node **rootp)
+{
+ int ret;
+
+ debug("%s: start\n", __func__);
+ ret = unflatten_device_tree(fdt_blob, rootp);
+ if (ret) {
+ debug("Failed to create live tree: err=%d\n", ret);
+ return ret;
+ }
+ ret = of_alias_scan();
+ if (ret) {
+ debug("Failed to scan live tree aliases: err=%d\n", ret);
+ return ret;
+ }
+ debug("%s: stop\n", __func__);
+
+ return ret;
+}
diff --git a/lib/oid_registry.c b/lib/oid_registry.c
new file mode 100644
index 00000000..209edc73
--- /dev/null
+++ b/lib/oid_registry.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* ASN.1 Object identifier (OID) registry
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#ifdef __UBOOT__
+#include <linux/compat.h>
+#else
+#include <linux/module.h>
+#include <linux/export.h>
+#endif
+#include <linux/oid_registry.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include "oid_registry_data.c"
+
+MODULE_DESCRIPTION("OID Registry");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
+/**
+ * look_up_OID - Find an OID registration for the specified data
+ * @data: Binary representation of the OID
+ * @datasize: Size of the binary representation
+ */
+enum OID look_up_OID(const void *data, size_t datasize)
+{
+ const unsigned char *octets = data;
+ enum OID oid;
+ unsigned char xhash;
+ unsigned i, j, k, hash;
+ size_t len;
+
+ /* Hash the OID data */
+ hash = datasize - 1;
+
+ for (i = 0; i < datasize; i++)
+ hash += octets[i] * 33;
+ hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash;
+ hash &= 0xff;
+
+ /* Binary search the OID registry. OIDs are stored in ascending order
+ * of hash value then ascending order of size and then in ascending
+ * order of reverse value.
+ */
+ i = 0;
+ k = OID__NR;
+ while (i < k) {
+ j = (i + k) / 2;
+
+ xhash = oid_search_table[j].hash;
+ if (xhash > hash) {
+ k = j;
+ continue;
+ }
+ if (xhash < hash) {
+ i = j + 1;
+ continue;
+ }
+
+ oid = oid_search_table[j].oid;
+ len = oid_index[oid + 1] - oid_index[oid];
+ if (len > datasize) {
+ k = j;
+ continue;
+ }
+ if (len < datasize) {
+ i = j + 1;
+ continue;
+ }
+
+ /* Variation is most likely to be at the tail end of the
+ * OID, so do the comparison in reverse.
+ */
+ while (len > 0) {
+ unsigned char a = oid_data[oid_index[oid] + --len];
+ unsigned char b = octets[len];
+ if (a > b) {
+ k = j;
+ goto next;
+ }
+ if (a < b) {
+ i = j + 1;
+ goto next;
+ }
+ }
+ return oid;
+ next:
+ ;
+ }
+
+ return OID__NR;
+}
+EXPORT_SYMBOL_GPL(look_up_OID);
+
+/*
+ * sprint_OID - Print an Object Identifier into a buffer
+ * @data: The encoded OID to print
+ * @datasize: The size of the encoded OID
+ * @buffer: The buffer to render into
+ * @bufsize: The size of the buffer
+ *
+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of
+ * bytes is returned. -EBADMSG is returned if the data could not be intepreted
+ * and -ENOBUFS if the buffer was too small.
+ */
+int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
+{
+ const unsigned char *v = data, *end = v + datasize;
+ unsigned long num;
+ unsigned char n;
+ size_t ret;
+ int count;
+
+ if (v >= end)
+ goto bad;
+
+ n = *v++;
+ ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
+ if (count >= bufsize)
+ return -ENOBUFS;
+ buffer += count;
+ bufsize -= count;
+
+ while (v < end) {
+ num = 0;
+ n = *v++;
+ if (!(n & 0x80)) {
+ num = n;
+ } else {
+ num = n & 0x7f;
+ do {
+ if (v >= end)
+ goto bad;
+ n = *v++;
+ num <<= 7;
+ num |= n & 0x7f;
+ } while (n & 0x80);
+ }
+ ret += count = snprintf(buffer, bufsize, ".%lu", num);
+ if (count >= bufsize)
+ return -ENOBUFS;
+ buffer += count;
+ bufsize -= count;
+ }
+
+ return ret;
+
+bad:
+ snprintf(buffer, bufsize, "(bad)");
+ return -EBADMSG;
+}
+EXPORT_SYMBOL_GPL(sprint_oid);
+
+/**
+ * sprint_OID - Print an Object Identifier into a buffer
+ * @oid: The OID to print
+ * @buffer: The buffer to render into
+ * @bufsize: The size of the buffer
+ *
+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of
+ * bytes is returned.
+ */
+int sprint_OID(enum OID oid, char *buffer, size_t bufsize)
+{
+ int ret;
+
+ BUG_ON(oid >= OID__NR);
+
+ ret = sprint_oid(oid_data + oid_index[oid],
+ oid_index[oid + 1] - oid_index[oid],
+ buffer, bufsize);
+ BUG_ON(ret == -EBADMSG);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sprint_OID);
diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig
new file mode 100644
index 00000000..c398f9b9
--- /dev/null
+++ b/lib/optee/Kconfig
@@ -0,0 +1,41 @@
+config OPTEE
+ bool "Support OPTEE images"
+ help
+ U-Boot can be configured to boot OPTEE images.
+ Selecting this option will enable shared OPTEE library code and
+ enable an OPTEE specific bootm command that will perform additional
+ OPTEE specific checks before booting an OPTEE image created with
+ mkimage.
+
+config OPTEE_LOAD_ADDR
+ hex "OPTEE load address"
+ default 0x00000000
+ depends on OPTEE
+ help
+ The load address of the bootable OPTEE binary.
+
+config OPTEE_TZDRAM_SIZE
+ hex "Amount of Trust-Zone RAM for the OPTEE image"
+ default 0x0000000
+ depends on OPTEE
+ help
+ The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE
+ runtime.
+
+config OPTEE_TZDRAM_BASE
+ hex "Base address of Trust-Zone RAM for the OPTEE image"
+ default 0x00000000
+ depends on OPTEE
+ help
+ The base address of pre-allocated Trust Zone DRAM for
+ the OPTEE runtime.
+
+config BOOTM_OPTEE
+ bool "Support OPTEE bootm command"
+ select BOOTM_LINUX
+ depends on OPTEE
+ default n
+ help
+ Select this command to enable chain-loading of a Linux kernel
+ via an OPTEE firmware.
+ The bootflow is BootROM -> u-boot -> OPTEE -> Linux in this case.
diff --git a/lib/optee/Makefile b/lib/optee/Makefile
new file mode 100644
index 00000000..b6923118
--- /dev/null
+++ b/lib/optee/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2017 Linaro
+
+obj-$(CONFIG_OPTEE) += optee.o
diff --git a/lib/optee/optee.c b/lib/optee/optee.c
new file mode 100644
index 00000000..c883c498
--- /dev/null
+++ b/lib/optee/optee.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Linaro
+ * Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <linux/libfdt.h>
+#include <tee/optee.h>
+
+#define optee_hdr_err_msg \
+ "OPTEE verification error:" \
+ "\n\thdr=%p image=0x%08lx magic=0x%08x tzdram 0x%08lx-0x%08lx " \
+ "\n\theader lo=0x%08x hi=0x%08x size=0x%08lx arch=0x%08x" \
+ "\n\tuimage params 0x%08lx-0x%08lx\n"
+
+int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start,
+ unsigned long tzdram_len, unsigned long image_len)
+{
+ unsigned long tzdram_end = tzdram_start + tzdram_len;
+ uint32_t tee_file_size;
+
+ tee_file_size = hdr->init_size + hdr->paged_size +
+ sizeof(struct optee_header);
+
+ if (hdr->magic != OPTEE_MAGIC ||
+ hdr->version != OPTEE_VERSION ||
+ hdr->init_load_addr_hi > tzdram_end ||
+ hdr->init_load_addr_lo < tzdram_start ||
+ tee_file_size > tzdram_len ||
+ tee_file_size != image_len ||
+ (hdr->init_load_addr_lo + tee_file_size) > tzdram_end) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int optee_verify_bootm_image(unsigned long image_addr,
+ unsigned long image_load_addr,
+ unsigned long image_len)
+{
+ struct optee_header *hdr = (struct optee_header *)image_addr;
+ unsigned long tzdram_start = CONFIG_OPTEE_TZDRAM_BASE;
+ unsigned long tzdram_len = CONFIG_OPTEE_TZDRAM_SIZE;
+
+ int ret;
+
+ ret = optee_verify_image(hdr, tzdram_start, tzdram_len, image_len);
+ if (ret)
+ goto error;
+
+ if (image_load_addr + sizeof(*hdr) != hdr->init_load_addr_lo) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ return ret;
+error:
+ printf(optee_hdr_err_msg, hdr, image_addr, hdr->magic, tzdram_start,
+ tzdram_start + tzdram_len, hdr->init_load_addr_lo,
+ hdr->init_load_addr_hi, image_len, hdr->arch, image_load_addr,
+ image_load_addr + image_len);
+
+ return ret;
+}
+
+#if defined(CONFIG_OF_LIBFDT)
+static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob)
+{
+ int old_offs, offs, ret, len;
+ const void *prop;
+
+ old_offs = fdt_path_offset(old_blob, "/firmware/optee");
+ if (old_offs < 0) {
+ debug("Original OP-TEE Device Tree node not found");
+ return old_offs;
+ }
+
+ offs = fdt_path_offset(fdt_blob, "/firmware");
+ if (offs < 0) {
+ offs = fdt_path_offset(fdt_blob, "/");
+ if (offs < 0)
+ return offs;
+
+ offs = fdt_add_subnode(fdt_blob, offs, "firmware");
+ if (offs < 0)
+ return offs;
+ }
+
+ offs = fdt_add_subnode(fdt_blob, offs, "optee");
+ if (offs < 0)
+ return ret;
+
+ /* copy the compatible property */
+ prop = fdt_getprop(old_blob, old_offs, "compatible", &len);
+ if (!prop) {
+ debug("missing OP-TEE compatible property");
+ return -EINVAL;
+ }
+
+ ret = fdt_setprop(fdt_blob, offs, "compatible", prop, len);
+ if (ret < 0)
+ return ret;
+
+ /* copy the method property */
+ prop = fdt_getprop(old_blob, old_offs, "method", &len);
+ if (!prop) {
+ debug("missing OP-TEE method property");
+ return -EINVAL;
+ }
+
+ ret = fdt_setprop(fdt_blob, offs, "method", prop, len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int optee_copy_fdt_nodes(const void *old_blob, void *new_blob)
+{
+ int nodeoffset, subnode, ret;
+ struct fdt_resource res;
+
+ if (fdt_check_header(old_blob))
+ return -EINVAL;
+
+ if (fdt_check_header(new_blob))
+ return -EINVAL;
+
+ /* only proceed if there is an /firmware/optee node */
+ if (fdt_path_offset(old_blob, "/firmware/optee") < 0) {
+ debug("No OP-TEE firmware node in old fdt, nothing to do");
+ return 0;
+ }
+
+ /*
+ * Do not proceed if the target dt already has an OP-TEE node.
+ * In this case assume that the system knows better somehow,
+ * so do not interfere.
+ */
+ if (fdt_path_offset(new_blob, "/firmware/optee") >= 0) {
+ debug("OP-TEE Device Tree node already exists in target");
+ return 0;
+ }
+
+ ret = optee_copy_firmware_node(old_blob, new_blob);
+ if (ret < 0) {
+ printf("Failed to add OP-TEE firmware node\n");
+ return ret;
+ }
+
+ /* optee inserts its memory regions as reserved-memory nodes */
+ nodeoffset = fdt_subnode_offset(old_blob, 0, "reserved-memory");
+ if (nodeoffset >= 0) {
+ subnode = fdt_first_subnode(old_blob, nodeoffset);
+ while (subnode >= 0) {
+ const char *name = fdt_get_name(old_blob,
+ subnode, NULL);
+ if (!name)
+ return -EINVAL;
+
+ /* only handle optee reservations */
+ if (strncmp(name, "optee", 5))
+ continue;
+
+ /* check if this subnode has a reg property */
+ ret = fdt_get_resource(old_blob, subnode, "reg", 0,
+ &res);
+ if (!ret) {
+ struct fdt_memory carveout = {
+ .start = res.start,
+ .end = res.end,
+ };
+ char *oldname, *nodename, *tmp;
+
+ oldname = strdup(name);
+ if (!oldname)
+ return -ENOMEM;
+
+ tmp = oldname;
+ nodename = strsep(&tmp, "@");
+ if (!nodename) {
+ free(oldname);
+ return -EINVAL;
+ }
+
+ ret = fdtdec_add_reserved_memory(new_blob,
+ nodename,
+ &carveout,
+ NULL);
+ free(oldname);
+
+ if (ret < 0)
+ return ret;
+ }
+
+ subnode = fdt_next_subnode(old_blob, subnode);
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/lib/panic.c b/lib/panic.c
new file mode 100644
index 00000000..bae8a359
--- /dev/null
+++ b/lib/panic.c
@@ -0,0 +1,55 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <common.h>
+#if !defined(CONFIG_PANIC_HANG)
+#include <command.h>
+#endif
+
+static void panic_finish(void) __attribute__ ((noreturn));
+
+static void panic_finish(void)
+{
+ putc('\n');
+#if defined(CONFIG_PANIC_HANG)
+ hang();
+#else
+ udelay(100000); /* allow messages to go out */
+ do_reset(NULL, 0, 0, NULL);
+#endif
+ while (1)
+ ;
+}
+
+void panic_str(const char *str)
+{
+ puts(str);
+ panic_finish();
+}
+
+void panic(const char *fmt, ...)
+{
+#if CONFIG_IS_ENABLED(PRINTF)
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+#endif
+ panic_finish();
+}
+
+void __assert_fail(const char *assertion, const char *file, unsigned int line,
+ const char *function)
+{
+ /* This will not return */
+ panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
+ assertion);
+}
diff --git a/lib/physmem.c b/lib/physmem.c
new file mode 100644
index 00000000..84b191da
--- /dev/null
+++ b/lib/physmem.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <physmem.h>
+#include <linux/compiler.h>
+
+phys_addr_t __weak arch_phys_memset(phys_addr_t s, int c, phys_size_t n)
+{
+ void *s_ptr = map_sysmem(s, n);
+
+ assert(((phys_addr_t)(uintptr_t)s) == s);
+ assert(((phys_addr_t)(uintptr_t)(s + n)) == s + n);
+
+ return (phys_addr_t)(uintptr_t)memset(s_ptr, c, n);
+}
diff --git a/lib/qsort.c b/lib/qsort.c
new file mode 100644
index 00000000..f63d4ef7
--- /dev/null
+++ b/lib/qsort.c
@@ -0,0 +1,72 @@
+/*
+ * Code adapted from uClibc-0.9.30.3
+ *
+ * It is therefore covered by the GNU LESSER GENERAL PUBLIC LICENSE
+ * Version 2.1, February 1999
+ *
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+/* This code is derived from a public domain shell sort routine by
+ * Ray Gardner and found in Bob Stout's snippets collection. The
+ * original code is included below in an #if 0/#endif block.
+ *
+ * I modified it to avoid the possibility of overflow in the wgap
+ * calculation, as well as to reduce the generated code size with
+ * bcc and gcc. */
+
+#include <linux/types.h>
+#include <common.h>
+#include <exports.h>
+#include <sort.h>
+
+void qsort(void *base,
+ size_t nel,
+ size_t width,
+ int (*comp)(const void *, const void *))
+{
+ size_t wgap, i, j, k;
+ char tmp;
+
+ if ((nel > 1) && (width > 0)) {
+ assert(nel <= ((size_t)(-1)) / width); /* check for overflow */
+ wgap = 0;
+ do {
+ wgap = 3 * wgap + 1;
+ } while (wgap < (nel-1)/3);
+ /* From the above, we know that either wgap == 1 < nel or */
+ /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */
+ wgap *= width; /* So this can not overflow if wnel doesn't. */
+ nel *= width; /* Convert nel to 'wnel' */
+ do {
+ i = wgap;
+ do {
+ j = i;
+ do {
+ register char *a;
+ register char *b;
+
+ j -= wgap;
+ a = j + ((char *)base);
+ b = a + wgap;
+ if ((*comp)(a, b) <= 0) {
+ break;
+ }
+ k = width;
+ do {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ } while (--k);
+ } while (j >= wgap);
+ i += width;
+ } while (i < nel);
+ wgap = (wgap - width)/3;
+ } while (wgap);
+ }
+}
+
+int strcmp_compar(const void *p1, const void *p2)
+{
+ return strcmp(*(const char **)p1, *(const char **)p2);
+}
diff --git a/lib/rand.c b/lib/rand.c
new file mode 100644
index 00000000..d256baf5
--- /dev/null
+++ b/lib/rand.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Simple xorshift PRNG
+ * see http://www.jstatsoft.org/v08/i14/paper
+ *
+ * Copyright (c) 2012 Michael Walle
+ * Michael Walle <michael@walle.cc>
+ */
+
+#include <common.h>
+#include <rand.h>
+
+static unsigned int y = 1U;
+
+unsigned int rand_r(unsigned int *seedp)
+{
+ *seedp ^= (*seedp << 13);
+ *seedp ^= (*seedp >> 17);
+ *seedp ^= (*seedp << 5);
+
+ return *seedp;
+}
+
+unsigned int rand(void)
+{
+ return rand_r(&y);
+}
+
+void srand(unsigned int seed)
+{
+ y = seed;
+}
diff --git a/lib/rbtree.c b/lib/rbtree.c
new file mode 100644
index 00000000..333314ad
--- /dev/null
+++ b/lib/rbtree.c
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ Red Black Trees
+ (C) 1999 Andrea Arcangeli <andrea@suse.de>
+ (C) 2002 David Woodhouse <dwmw2@infradead.org>
+ (C) 2012 Michel Lespinasse <walken@google.com>
+
+ linux/lib/rbtree.c
+*/
+
+#include <linux/rbtree_augmented.h>
+#ifndef __UBOOT__
+#include <linux/export.h>
+#else
+#include <ubi_uboot.h>
+#endif
+/*
+ * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree
+ *
+ * 1) A node is either red or black
+ * 2) The root is black
+ * 3) All leaves (NULL) are black
+ * 4) Both children of every red node are black
+ * 5) Every simple path from root to leaves contains the same number
+ * of black nodes.
+ *
+ * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
+ * consecutive red nodes in a path and every red node is therefore followed by
+ * a black. So if B is the number of black nodes on every simple path (as per
+ * 5), then the longest possible path due to 4 is 2B.
+ *
+ * We shall indicate color with case, where black nodes are uppercase and red
+ * nodes will be lowercase. Unknown color nodes shall be drawn as red within
+ * parentheses and have some accompanying text comment.
+ */
+
+static inline void rb_set_black(struct rb_node *rb)
+{
+ rb->__rb_parent_color |= RB_BLACK;
+}
+
+static inline struct rb_node *rb_red_parent(struct rb_node *red)
+{
+ return (struct rb_node *)red->__rb_parent_color;
+}
+
+/*
+ * Helper function for rotations:
+ * - old's parent and color get assigned to new
+ * - old gets assigned new as a parent and 'color' as a color.
+ */
+static inline void
+__rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
+ struct rb_root *root, int color)
+{
+ struct rb_node *parent = rb_parent(old);
+ new->__rb_parent_color = old->__rb_parent_color;
+ rb_set_parent_color(old, new, color);
+ __rb_change_child(old, new, parent, root);
+}
+
+static __always_inline void
+__rb_insert(struct rb_node *node, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+ struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
+
+ while (true) {
+ /*
+ * Loop invariant: node is red
+ *
+ * If there is a black parent, we are done.
+ * Otherwise, take some corrective action as we don't
+ * want a red root or two consecutive red nodes.
+ */
+ if (!parent) {
+ rb_set_parent_color(node, NULL, RB_BLACK);
+ break;
+ } else if (rb_is_black(parent))
+ break;
+
+ gparent = rb_red_parent(parent);
+
+ tmp = gparent->rb_right;
+ if (parent != tmp) { /* parent == gparent->rb_left */
+ if (tmp && rb_is_red(tmp)) {
+ /*
+ * Case 1 - color flips
+ *
+ * G g
+ * / \ / \
+ * p u --> P U
+ * / /
+ * n N
+ *
+ * However, since g's parent might be red, and
+ * 4) does not allow this, we need to recurse
+ * at g.
+ */
+ rb_set_parent_color(tmp, gparent, RB_BLACK);
+ rb_set_parent_color(parent, gparent, RB_BLACK);
+ node = gparent;
+ parent = rb_parent(node);
+ rb_set_parent_color(node, parent, RB_RED);
+ continue;
+ }
+
+ tmp = parent->rb_right;
+ if (node == tmp) {
+ /*
+ * Case 2 - left rotate at parent
+ *
+ * G G
+ * / \ / \
+ * p U --> n U
+ * \ /
+ * n p
+ *
+ * This still leaves us in violation of 4), the
+ * continuation into Case 3 will fix that.
+ */
+ parent->rb_right = tmp = node->rb_left;
+ node->rb_left = parent;
+ if (tmp)
+ rb_set_parent_color(tmp, parent,
+ RB_BLACK);
+ rb_set_parent_color(parent, node, RB_RED);
+ augment_rotate(parent, node);
+ parent = node;
+ tmp = node->rb_right;
+ }
+
+ /*
+ * Case 3 - right rotate at gparent
+ *
+ * G P
+ * / \ / \
+ * p U --> n g
+ * / \
+ * n U
+ */
+ gparent->rb_left = tmp; /* == parent->rb_right */
+ parent->rb_right = gparent;
+ if (tmp)
+ rb_set_parent_color(tmp, gparent, RB_BLACK);
+ __rb_rotate_set_parents(gparent, parent, root, RB_RED);
+ augment_rotate(gparent, parent);
+ break;
+ } else {
+ tmp = gparent->rb_left;
+ if (tmp && rb_is_red(tmp)) {
+ /* Case 1 - color flips */
+ rb_set_parent_color(tmp, gparent, RB_BLACK);
+ rb_set_parent_color(parent, gparent, RB_BLACK);
+ node = gparent;
+ parent = rb_parent(node);
+ rb_set_parent_color(node, parent, RB_RED);
+ continue;
+ }
+
+ tmp = parent->rb_left;
+ if (node == tmp) {
+ /* Case 2 - right rotate at parent */
+ parent->rb_left = tmp = node->rb_right;
+ node->rb_right = parent;
+ if (tmp)
+ rb_set_parent_color(tmp, parent,
+ RB_BLACK);
+ rb_set_parent_color(parent, node, RB_RED);
+ augment_rotate(parent, node);
+ parent = node;
+ tmp = node->rb_left;
+ }
+
+ /* Case 3 - left rotate at gparent */
+ gparent->rb_right = tmp; /* == parent->rb_left */
+ parent->rb_left = gparent;
+ if (tmp)
+ rb_set_parent_color(tmp, gparent, RB_BLACK);
+ __rb_rotate_set_parents(gparent, parent, root, RB_RED);
+ augment_rotate(gparent, parent);
+ break;
+ }
+ }
+}
+
+/*
+ * Inline version for rb_erase() use - we want to be able to inline
+ * and eliminate the dummy_rotate callback there
+ */
+static __always_inline void
+____rb_erase_color(struct rb_node *parent, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+ struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
+
+ while (true) {
+ /*
+ * Loop invariants:
+ * - node is black (or NULL on first iteration)
+ * - node is not the root (parent is not NULL)
+ * - All leaf paths going through parent and node have a
+ * black node count that is 1 lower than other leaf paths.
+ */
+ sibling = parent->rb_right;
+ if (node != sibling) { /* node == parent->rb_left */
+ if (rb_is_red(sibling)) {
+ /*
+ * Case 1 - left rotate at parent
+ *
+ * P S
+ * / \ / \
+ * N s --> p Sr
+ * / \ / \
+ * Sl Sr N Sl
+ */
+ parent->rb_right = tmp1 = sibling->rb_left;
+ sibling->rb_left = parent;
+ rb_set_parent_color(tmp1, parent, RB_BLACK);
+ __rb_rotate_set_parents(parent, sibling, root,
+ RB_RED);
+ augment_rotate(parent, sibling);
+ sibling = tmp1;
+ }
+ tmp1 = sibling->rb_right;
+ if (!tmp1 || rb_is_black(tmp1)) {
+ tmp2 = sibling->rb_left;
+ if (!tmp2 || rb_is_black(tmp2)) {
+ /*
+ * Case 2 - sibling color flip
+ * (p could be either color here)
+ *
+ * (p) (p)
+ * / \ / \
+ * N S --> N s
+ * / \ / \
+ * Sl Sr Sl Sr
+ *
+ * This leaves us violating 5) which
+ * can be fixed by flipping p to black
+ * if it was red, or by recursing at p.
+ * p is red when coming from Case 1.
+ */
+ rb_set_parent_color(sibling, parent,
+ RB_RED);
+ if (rb_is_red(parent))
+ rb_set_black(parent);
+ else {
+ node = parent;
+ parent = rb_parent(node);
+ if (parent)
+ continue;
+ }
+ break;
+ }
+ /*
+ * Case 3 - right rotate at sibling
+ * (p could be either color here)
+ *
+ * (p) (p)
+ * / \ / \
+ * N S --> N Sl
+ * / \ \
+ * sl Sr s
+ * \
+ * Sr
+ */
+ sibling->rb_left = tmp1 = tmp2->rb_right;
+ tmp2->rb_right = sibling;
+ parent->rb_right = tmp2;
+ if (tmp1)
+ rb_set_parent_color(tmp1, sibling,
+ RB_BLACK);
+ augment_rotate(sibling, tmp2);
+ tmp1 = sibling;
+ sibling = tmp2;
+ }
+ /*
+ * Case 4 - left rotate at parent + color flips
+ * (p and sl could be either color here.
+ * After rotation, p becomes black, s acquires
+ * p's color, and sl keeps its color)
+ *
+ * (p) (s)
+ * / \ / \
+ * N S --> P Sr
+ * / \ / \
+ * (sl) sr N (sl)
+ */
+ parent->rb_right = tmp2 = sibling->rb_left;
+ sibling->rb_left = parent;
+ rb_set_parent_color(tmp1, sibling, RB_BLACK);
+ if (tmp2)
+ rb_set_parent(tmp2, parent);
+ __rb_rotate_set_parents(parent, sibling, root,
+ RB_BLACK);
+ augment_rotate(parent, sibling);
+ break;
+ } else {
+ sibling = parent->rb_left;
+ if (rb_is_red(sibling)) {
+ /* Case 1 - right rotate at parent */
+ parent->rb_left = tmp1 = sibling->rb_right;
+ sibling->rb_right = parent;
+ rb_set_parent_color(tmp1, parent, RB_BLACK);
+ __rb_rotate_set_parents(parent, sibling, root,
+ RB_RED);
+ augment_rotate(parent, sibling);
+ sibling = tmp1;
+ }
+ tmp1 = sibling->rb_left;
+ if (!tmp1 || rb_is_black(tmp1)) {
+ tmp2 = sibling->rb_right;
+ if (!tmp2 || rb_is_black(tmp2)) {
+ /* Case 2 - sibling color flip */
+ rb_set_parent_color(sibling, parent,
+ RB_RED);
+ if (rb_is_red(parent))
+ rb_set_black(parent);
+ else {
+ node = parent;
+ parent = rb_parent(node);
+ if (parent)
+ continue;
+ }
+ break;
+ }
+ /* Case 3 - right rotate at sibling */
+ sibling->rb_right = tmp1 = tmp2->rb_left;
+ tmp2->rb_left = sibling;
+ parent->rb_left = tmp2;
+ if (tmp1)
+ rb_set_parent_color(tmp1, sibling,
+ RB_BLACK);
+ augment_rotate(sibling, tmp2);
+ tmp1 = sibling;
+ sibling = tmp2;
+ }
+ /* Case 4 - left rotate at parent + color flips */
+ parent->rb_left = tmp2 = sibling->rb_right;
+ sibling->rb_right = parent;
+ rb_set_parent_color(tmp1, sibling, RB_BLACK);
+ if (tmp2)
+ rb_set_parent(tmp2, parent);
+ __rb_rotate_set_parents(parent, sibling, root,
+ RB_BLACK);
+ augment_rotate(parent, sibling);
+ break;
+ }
+ }
+}
+
+/* Non-inline version for rb_erase_augmented() use */
+void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+ ____rb_erase_color(parent, root, augment_rotate);
+}
+EXPORT_SYMBOL(__rb_erase_color);
+
+/*
+ * Non-augmented rbtree manipulation functions.
+ *
+ * We use dummy augmented callbacks here, and have the compiler optimize them
+ * out of the rb_insert_color() and rb_erase() function definitions.
+ */
+
+static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}
+static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
+static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
+
+static const struct rb_augment_callbacks dummy_callbacks = {
+ dummy_propagate, dummy_copy, dummy_rotate
+};
+
+void rb_insert_color(struct rb_node *node, struct rb_root *root)
+{
+ __rb_insert(node, root, dummy_rotate);
+}
+EXPORT_SYMBOL(rb_insert_color);
+
+void rb_erase(struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *rebalance;
+ rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
+ if (rebalance)
+ ____rb_erase_color(rebalance, root, dummy_rotate);
+}
+EXPORT_SYMBOL(rb_erase);
+
+/*
+ * Augmented rbtree manipulation functions.
+ *
+ * This instantiates the same __always_inline functions as in the non-augmented
+ * case, but this time with user-defined callbacks.
+ */
+
+void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+ __rb_insert(node, root, augment_rotate);
+}
+EXPORT_SYMBOL(__rb_insert_augmented);
+
+/*
+ * This function returns the first node (in sort order) of the tree.
+ */
+struct rb_node *rb_first(const struct rb_root *root)
+{
+ struct rb_node *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_left)
+ n = n->rb_left;
+ return n;
+}
+EXPORT_SYMBOL(rb_first);
+
+struct rb_node *rb_last(const struct rb_root *root)
+{
+ struct rb_node *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_right)
+ n = n->rb_right;
+ return n;
+}
+EXPORT_SYMBOL(rb_last);
+
+struct rb_node *rb_next(const struct rb_node *node)
+{
+ struct rb_node *parent;
+
+ if (RB_EMPTY_NODE(node))
+ return NULL;
+
+ /*
+ * If we have a right-hand child, go down and then left as far
+ * as we can.
+ */
+ if (node->rb_right) {
+ node = node->rb_right;
+ while (node->rb_left)
+ node=node->rb_left;
+ return (struct rb_node *)node;
+ }
+
+ /*
+ * No right-hand children. Everything down and left is smaller than us,
+ * so any 'next' node must be in the general direction of our parent.
+ * Go up the tree; any time the ancestor is a right-hand child of its
+ * parent, keep going up. First time it's a left-hand child of its
+ * parent, said parent is our 'next' node.
+ */
+ while ((parent = rb_parent(node)) && node == parent->rb_right)
+ node = parent;
+
+ return parent;
+}
+EXPORT_SYMBOL(rb_next);
+
+struct rb_node *rb_prev(const struct rb_node *node)
+{
+ struct rb_node *parent;
+
+ if (RB_EMPTY_NODE(node))
+ return NULL;
+
+ /*
+ * If we have a left-hand child, go down and then right as far
+ * as we can.
+ */
+ if (node->rb_left) {
+ node = node->rb_left;
+ while (node->rb_right)
+ node=node->rb_right;
+ return (struct rb_node *)node;
+ }
+
+ /*
+ * No left-hand children. Go up till we find an ancestor which
+ * is a right-hand child of its parent.
+ */
+ while ((parent = rb_parent(node)) && node == parent->rb_left)
+ node = parent;
+
+ return parent;
+}
+EXPORT_SYMBOL(rb_prev);
+
+void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+ struct rb_root *root)
+{
+ struct rb_node *parent = rb_parent(victim);
+
+ /* Set the surrounding nodes to point to the replacement */
+ __rb_change_child(victim, new, parent, root);
+ if (victim->rb_left)
+ rb_set_parent(victim->rb_left, new);
+ if (victim->rb_right)
+ rb_set_parent(victim->rb_right, new);
+
+ /* Copy the pointers/colour from the victim to the replacement */
+ *new = *victim;
+}
+EXPORT_SYMBOL(rb_replace_node);
+
+static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
+{
+ for (;;) {
+ if (node->rb_left)
+ node = node->rb_left;
+ else if (node->rb_right)
+ node = node->rb_right;
+ else
+ return (struct rb_node *)node;
+ }
+}
+
+struct rb_node *rb_next_postorder(const struct rb_node *node)
+{
+ const struct rb_node *parent;
+ if (!node)
+ return NULL;
+ parent = rb_parent(node);
+
+ /* If we're sitting on node, we've already seen our children */
+ if (parent && node == parent->rb_left && parent->rb_right) {
+ /* If we are the parent's left node, go to the parent's right
+ * node then all the way down to the left */
+ return rb_left_deepest_node(parent->rb_right);
+ } else
+ /* Otherwise we are the parent's right node, and the parent
+ * should be next */
+ return (struct rb_node *)parent;
+}
+EXPORT_SYMBOL(rb_next_postorder);
+
+struct rb_node *rb_first_postorder(const struct rb_root *root)
+{
+ if (!root->rb_node)
+ return NULL;
+
+ return rb_left_deepest_node(root->rb_node);
+}
+EXPORT_SYMBOL(rb_first_postorder);
diff --git a/lib/rc4.c b/lib/rc4.c
new file mode 100644
index 00000000..0c004398
--- /dev/null
+++ b/lib/rc4.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ *
+ * Rivest Cipher 4 (RC4) implementation
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#endif
+#include <rc4.h>
+
+void rc4_encode(unsigned char *buf, unsigned int len, unsigned char key[16])
+{
+ unsigned char s[256], k[256], temp;
+ unsigned short i, j, t;
+ int ptr;
+
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ s[i] = (unsigned char)i;
+ j &= 0x0f;
+ k[i] = key[j];
+ j++;
+ }
+
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ j = (j + s[i] + k[i]) % 256;
+ temp = s[i];
+ s[i] = s[j];
+ s[j] = temp;
+ }
+
+ i = 0;
+ j = 0;
+ for (ptr = 0; ptr < len; ptr++) {
+ i = (i + 1) % 256;
+ j = (j + s[i]) % 256;
+ temp = s[i];
+ s[i] = s[j];
+ s[j] = temp;
+ t = (s[i] + (s[j] % 256)) % 256;
+ buf[ptr] = buf[ptr] ^ s[t];
+ }
+}
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig
new file mode 100644
index 00000000..2b33f323
--- /dev/null
+++ b/lib/rsa/Kconfig
@@ -0,0 +1,37 @@
+config RSA
+ bool "Use RSA Library"
+ select RSA_FREESCALE_EXP if FSL_CAAM && !ARCH_MX7 && !ARCH_MX6 && !ARCH_MX5
+ select RSA_SOFTWARE_EXP if !RSA_FREESCALE_EXP
+ help
+ RSA support. This enables the RSA algorithm used for FIT image
+ verification in U-Boot.
+ See doc/uImage.FIT/signature.txt for more details.
+ The Modular Exponentiation algorithm in RSA is implemented using
+ driver model. So CONFIG_DM needs to be enabled by default for this
+ library to function.
+ The signing part is build into mkimage regardless of this
+ option. The software based modular exponentiation is built into
+ mkimage irrespective of this option.
+
+if RSA
+
+config SPL_RSA
+ bool "Use RSA Library within SPL"
+
+config RSA_SOFTWARE_EXP
+ bool "Enable driver for RSA Modular Exponentiation in software"
+ depends on DM
+ help
+ Enables driver for modular exponentiation in software. This is a RSA
+ algorithm used in FIT image verification. It required RSA Key as
+ input.
+ See doc/uImage.FIT/signature.txt for more details.
+
+config RSA_FREESCALE_EXP
+ bool "Enable RSA Modular Exponentiation with FSL crypto accelerator"
+ depends on DM && FSL_CAAM && !ARCH_MX7 && !ARCH_MX6 && !ARCH_MX5
+ help
+ Enables driver for RSA modular exponentiation using Freescale cryptographic
+ accelerator - CAAM.
+
+endif
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
new file mode 100644
index 00000000..a51c6e16
--- /dev/null
+++ b/lib/rsa/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2013, Google Inc.
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-$(CONFIG_$(SPL_)FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
+obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o
diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c
new file mode 100644
index 00000000..e60debb7
--- /dev/null
+++ b/lib/rsa/rsa-checksum.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Andreas Oetken.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <asm/unaligned.h>
+#include <hash.h>
+#else
+#include "fdt_host.h"
+#endif
+#include <u-boot/rsa.h>
+
+int hash_calculate(const char *name,
+ const struct image_region region[],
+ int region_count, uint8_t *checksum)
+{
+ struct hash_algo *algo;
+ int ret = 0;
+ void *ctx;
+ uint32_t i;
+ i = 0;
+
+ ret = hash_progressive_lookup_algo(name, &algo);
+ if (ret)
+ return ret;
+
+ ret = algo->hash_init(algo, &ctx);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < region_count - 1; i++) {
+ ret = algo->hash_update(algo, ctx, region[i].data,
+ region[i].size, 0);
+ if (ret)
+ return ret;
+ }
+
+ ret = algo->hash_update(algo, ctx, region[i].data, region[i].size, 1);
+ if (ret)
+ return ret;
+ ret = algo->hash_finish(algo, ctx, checksum, algo->digest_size);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c
new file mode 100644
index 00000000..420ab2eb
--- /dev/null
+++ b/lib/rsa/rsa-mod-exp.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Google Inc.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <asm/types.h>
+#include <asm/unaligned.h>
+#else
+#include "fdt_host.h"
+#include "mkimage.h"
+#include <fdt_support.h>
+#endif
+#include <u-boot/rsa.h>
+#include <u-boot/rsa-mod-exp.h>
+
+#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
+#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
+
+/* Default public exponent for backward compatibility */
+#define RSA_DEFAULT_PUBEXP 65537
+
+/**
+ * subtract_modulus() - subtract modulus from the given value
+ *
+ * @key: Key containing modulus to subtract
+ * @num: Number to subtract modulus from, as little endian word array
+ */
+static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
+{
+ int64_t acc = 0;
+ uint i;
+
+ for (i = 0; i < key->len; i++) {
+ acc += (uint64_t)num[i] - key->modulus[i];
+ num[i] = (uint32_t)acc;
+ acc >>= 32;
+ }
+}
+
+/**
+ * greater_equal_modulus() - check if a value is >= modulus
+ *
+ * @key: Key containing modulus to check
+ * @num: Number to check against modulus, as little endian word array
+ * @return 0 if num < modulus, 1 if num >= modulus
+ */
+static int greater_equal_modulus(const struct rsa_public_key *key,
+ uint32_t num[])
+{
+ int i;
+
+ for (i = (int)key->len - 1; i >= 0; i--) {
+ if (num[i] < key->modulus[i])
+ return 0;
+ if (num[i] > key->modulus[i])
+ return 1;
+ }
+
+ return 1; /* equal */
+}
+
+/**
+ * montgomery_mul_add_step() - Perform montgomery multiply-add step
+ *
+ * Operation: montgomery result[] += a * b[] / n0inv % modulus
+ *
+ * @key: RSA key
+ * @result: Place to put result, as little endian word array
+ * @a: Multiplier
+ * @b: Multiplicand, as little endian word array
+ */
+static void montgomery_mul_add_step(const struct rsa_public_key *key,
+ uint32_t result[], const uint32_t a, const uint32_t b[])
+{
+ uint64_t acc_a, acc_b;
+ uint32_t d0;
+ uint i;
+
+ acc_a = (uint64_t)a * b[0] + result[0];
+ d0 = (uint32_t)acc_a * key->n0inv;
+ acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
+ for (i = 1; i < key->len; i++) {
+ acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
+ acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
+ (uint32_t)acc_a;
+ result[i - 1] = (uint32_t)acc_b;
+ }
+
+ acc_a = (acc_a >> 32) + (acc_b >> 32);
+
+ result[i - 1] = (uint32_t)acc_a;
+
+ if (acc_a >> 32)
+ subtract_modulus(key, result);
+}
+
+/**
+ * montgomery_mul() - Perform montgomery mutitply
+ *
+ * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
+ *
+ * @key: RSA key
+ * @result: Place to put result, as little endian word array
+ * @a: Multiplier, as little endian word array
+ * @b: Multiplicand, as little endian word array
+ */
+static void montgomery_mul(const struct rsa_public_key *key,
+ uint32_t result[], uint32_t a[], const uint32_t b[])
+{
+ uint i;
+
+ for (i = 0; i < key->len; ++i)
+ result[i] = 0;
+ for (i = 0; i < key->len; ++i)
+ montgomery_mul_add_step(key, result, a[i], b);
+}
+
+/**
+ * num_pub_exponent_bits() - Number of bits in the public exponent
+ *
+ * @key: RSA key
+ * @num_bits: Storage for the number of public exponent bits
+ */
+static int num_public_exponent_bits(const struct rsa_public_key *key,
+ int *num_bits)
+{
+ uint64_t exponent;
+ int exponent_bits;
+ const uint max_bits = (sizeof(exponent) * 8);
+
+ exponent = key->exponent;
+ exponent_bits = 0;
+
+ if (!exponent) {
+ *num_bits = exponent_bits;
+ return 0;
+ }
+
+ for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
+ if (!(exponent >>= 1)) {
+ *num_bits = exponent_bits;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
+ *
+ * @key: RSA key
+ * @pos: The bit position to check
+ */
+static int is_public_exponent_bit_set(const struct rsa_public_key *key,
+ int pos)
+{
+ return key->exponent & (1ULL << pos);
+}
+
+/**
+ * pow_mod() - in-place public exponentiation
+ *
+ * @key: RSA key
+ * @inout: Big-endian word array containing value and result
+ */
+static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
+{
+ uint32_t *result, *ptr;
+ uint i;
+ int j, k;
+
+ /* Sanity check for stack size - key->len is in 32-bit words */
+ if (key->len > RSA_MAX_KEY_BITS / 32) {
+ debug("RSA key words %u exceeds maximum %d\n", key->len,
+ RSA_MAX_KEY_BITS / 32);
+ return -EINVAL;
+ }
+
+ uint32_t val[key->len], acc[key->len], tmp[key->len];
+ uint32_t a_scaled[key->len];
+ result = tmp; /* Re-use location. */
+
+ /* Convert from big endian byte array to little endian word array. */
+ for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
+ val[i] = get_unaligned_be32(ptr);
+
+ if (0 != num_public_exponent_bits(key, &k))
+ return -EINVAL;
+
+ if (k < 2) {
+ debug("Public exponent is too short (%d bits, minimum 2)\n",
+ k);
+ return -EINVAL;
+ }
+
+ if (!is_public_exponent_bit_set(key, 0)) {
+ debug("LSB of RSA public exponent must be set.\n");
+ return -EINVAL;
+ }
+
+ /* the bit at e[k-1] is 1 by definition, so start with: C := M */
+ montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
+ /* retain scaled version for intermediate use */
+ memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
+
+ for (j = k - 2; j > 0; --j) {
+ montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+
+ if (is_public_exponent_bit_set(key, j)) {
+ /* acc = tmp * val / R mod n */
+ montgomery_mul(key, acc, tmp, a_scaled);
+ } else {
+ /* e[j] == 0, copy tmp back to acc for next operation */
+ memcpy(acc, tmp, key->len * sizeof(acc[0]));
+ }
+ }
+
+ /* the bit at e[0] is always 1 */
+ montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+ montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
+ memcpy(result, acc, key->len * sizeof(result[0]));
+
+ /* Make sure result < mod; result is at most 1x mod too large. */
+ if (greater_equal_modulus(key, result))
+ subtract_modulus(key, result);
+
+ /* Convert to bigendian byte array */
+ for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
+ put_unaligned_be32(result[i], ptr);
+ return 0;
+}
+
+static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = fdt32_to_cpu(src[len - 1 - i]);
+}
+
+int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
+ struct key_prop *prop, uint8_t *out)
+{
+ struct rsa_public_key key;
+ int ret;
+
+ if (!prop) {
+ debug("%s: Skipping invalid prop", __func__);
+ return -EBADF;
+ }
+ key.n0inv = prop->n0inv;
+ key.len = prop->num_bits;
+
+ if (!prop->public_exponent)
+ key.exponent = RSA_DEFAULT_PUBEXP;
+ else
+ key.exponent =
+ fdt64_to_cpu(*((uint64_t *)(prop->public_exponent)));
+
+ if (!key.len || !prop->modulus || !prop->rr) {
+ debug("%s: Missing RSA key info", __func__);
+ return -EFAULT;
+ }
+
+ /* Sanity check for stack size */
+ if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
+ debug("RSA key bits %u outside allowed range %d..%d\n",
+ key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+ return -EFAULT;
+ }
+ key.len /= sizeof(uint32_t) * 8;
+ uint32_t key1[key.len], key2[key.len];
+
+ key.modulus = key1;
+ key.rr = key2;
+ rsa_convert_big_endian(key.modulus, (uint32_t *)prop->modulus, key.len);
+ rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len);
+ if (!key.modulus || !key.rr) {
+ debug("%s: Out of memory", __func__);
+ return -ENOMEM;
+ }
+
+ uint32_t buf[sig_len / sizeof(uint32_t)];
+
+ memcpy(buf, sig, sig_len);
+
+ ret = pow_mod(&key, buf);
+ if (ret)
+ return ret;
+
+ memcpy(out, buf, sig_len);
+
+ return 0;
+}
+
+#if defined(CONFIG_CMD_ZYNQ_RSA)
+/**
+ * zynq_pow_mod - in-place public exponentiation
+ *
+ * @keyptr: RSA key
+ * @inout: Big-endian word array containing value and result
+ * @return 0 on successful calculation, otherwise failure error code
+ *
+ * FIXME: Use pow_mod() instead of zynq_pow_mod()
+ * pow_mod calculation required for zynq is bit different from
+ * pw_mod above here, hence defined zynq specific routine.
+ */
+int zynq_pow_mod(u32 *keyptr, u32 *inout)
+{
+ u32 *result, *ptr;
+ uint i;
+ struct rsa_public_key *key;
+ u32 val[RSA2048_BYTES], acc[RSA2048_BYTES], tmp[RSA2048_BYTES];
+
+ key = (struct rsa_public_key *)keyptr;
+
+ /* Sanity check for stack size - key->len is in 32-bit words */
+ if (key->len > RSA_MAX_KEY_BITS / 32) {
+ debug("RSA key words %u exceeds maximum %d\n", key->len,
+ RSA_MAX_KEY_BITS / 32);
+ return -EINVAL;
+ }
+
+ result = tmp; /* Re-use location. */
+
+ for (i = 0, ptr = inout; i < key->len; i++, ptr++)
+ val[i] = *(ptr);
+
+ montgomery_mul(key, acc, val, key->rr); /* axx = a * RR / R mod M */
+ for (i = 0; i < 16; i += 2) {
+ montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
+ montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
+ }
+ montgomery_mul(key, result, acc, val); /* result = XX * a / R mod M */
+
+ /* Make sure result < mod; result is at most 1x mod too large. */
+ if (greater_equal_modulus(key, result))
+ subtract_modulus(key, result);
+
+ for (i = 0, ptr = inout; i < key->len; i++, ptr++)
+ *ptr = result[i];
+
+ return 0;
+}
+#endif
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
new file mode 100644
index 00000000..5b5905ae
--- /dev/null
+++ b/lib/rsa/rsa-sign.c
@@ -0,0 +1,832 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Google Inc.
+ */
+
+#include "mkimage.h"
+#include <stdio.h>
+#include <string.h>
+#include <image.h>
+#include <time.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define HAVE_ERR_REMOVE_THREAD_STATE
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+static void RSA_get0_key(const RSA *r,
+ const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+ if (n != NULL)
+ *n = r->n;
+ if (e != NULL)
+ *e = r->e;
+ if (d != NULL)
+ *d = r->d;
+}
+#endif
+
+static int rsa_err(const char *msg)
+{
+ unsigned long sslErr = ERR_get_error();
+
+ fprintf(stderr, "%s", msg);
+ fprintf(stderr, ": %s\n",
+ ERR_error_string(sslErr, 0));
+
+ return -1;
+}
+
+/**
+ * rsa_pem_get_pub_key() - read a public key from a .crt file
+ *
+ * @keydir: Directory containins the key
+ * @name Name of key file (will have a .crt extension)
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+{
+ char path[1024];
+ EVP_PKEY *key;
+ X509 *cert;
+ RSA *rsa;
+ FILE *f;
+ int ret;
+
+ *rsap = NULL;
+ snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
+ f = fopen(path, "r");
+ if (!f) {
+ fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
+ path, strerror(errno));
+ return -EACCES;
+ }
+
+ /* Read the certificate */
+ cert = NULL;
+ if (!PEM_read_X509(f, &cert, NULL, NULL)) {
+ rsa_err("Couldn't read certificate");
+ ret = -EINVAL;
+ goto err_cert;
+ }
+
+ /* Get the public key from the certificate. */
+ key = X509_get_pubkey(cert);
+ if (!key) {
+ rsa_err("Couldn't read public key\n");
+ ret = -EINVAL;
+ goto err_pubkey;
+ }
+
+ /* Convert to a RSA_style key. */
+ rsa = EVP_PKEY_get1_RSA(key);
+ if (!rsa) {
+ rsa_err("Couldn't convert to a RSA style key");
+ ret = -EINVAL;
+ goto err_rsa;
+ }
+ fclose(f);
+ EVP_PKEY_free(key);
+ X509_free(cert);
+ *rsap = rsa;
+
+ return 0;
+
+err_rsa:
+ EVP_PKEY_free(key);
+err_pubkey:
+ X509_free(cert);
+err_cert:
+ fclose(f);
+ return ret;
+}
+
+/**
+ * rsa_engine_get_pub_key() - read a public key from given engine
+ *
+ * @keydir: Key prefix
+ * @name Name of key
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_pub_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ const char *engine_id;
+ char key_id[1024];
+ EVP_PKEY *key;
+ RSA *rsa;
+ int ret;
+
+ *rsap = NULL;
+
+ engine_id = ENGINE_get_id(engine);
+
+ if (engine_id && !strcmp(engine_id, "pkcs11")) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:%s;object=%s;type=public",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:object=%s;type=public",
+ name);
+ } else if (engine_id) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "%s%s",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "%s",
+ name);
+ } else {
+ fprintf(stderr, "Engine not supported\n");
+ return -ENOTSUP;
+ }
+
+ key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
+ if (!key)
+ return rsa_err("Failure loading public key from engine");
+
+ /* Convert to a RSA_style key. */
+ rsa = EVP_PKEY_get1_RSA(key);
+ if (!rsa) {
+ rsa_err("Couldn't convert to a RSA style key");
+ ret = -EINVAL;
+ goto err_rsa;
+ }
+
+ EVP_PKEY_free(key);
+ *rsap = rsa;
+
+ return 0;
+
+err_rsa:
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key
+ *
+ * @keydir: Directory containing the key (PEM file) or key prefix (engine)
+ * @name Name of key file (will have a .crt extension)
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ if (engine)
+ return rsa_engine_get_pub_key(keydir, name, engine, rsap);
+ return rsa_pem_get_pub_key(keydir, name, rsap);
+}
+
+/**
+ * rsa_pem_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir: Directory containing the key
+ * @name Name of key file (will have a .key extension)
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_pem_get_priv_key(const char *keydir, const char *name,
+ RSA **rsap)
+{
+ char path[1024];
+ RSA *rsa;
+ FILE *f;
+
+ *rsap = NULL;
+ snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
+ f = fopen(path, "r");
+ if (!f) {
+ fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
+ path, strerror(errno));
+ return -ENOENT;
+ }
+
+ rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
+ if (!rsa) {
+ rsa_err("Failure reading private key");
+ fclose(f);
+ return -EPROTO;
+ }
+ fclose(f);
+ *rsap = rsa;
+
+ return 0;
+}
+
+/**
+ * rsa_engine_get_priv_key() - read a private key from given engine
+ *
+ * @keydir: Key prefix
+ * @name Name of key
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_priv_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ const char *engine_id;
+ char key_id[1024];
+ EVP_PKEY *key;
+ RSA *rsa;
+ int ret;
+
+ *rsap = NULL;
+
+ engine_id = ENGINE_get_id(engine);
+
+ if (engine_id && !strcmp(engine_id, "pkcs11")) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:%s;object=%s;type=private",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:object=%s;type=private",
+ name);
+ } else if (engine_id) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "%s%s",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "%s",
+ name);
+ } else {
+ fprintf(stderr, "Engine not supported\n");
+ return -ENOTSUP;
+ }
+
+ key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
+ if (!key)
+ return rsa_err("Failure loading private key from engine");
+
+ /* Convert to a RSA_style key. */
+ rsa = EVP_PKEY_get1_RSA(key);
+ if (!rsa) {
+ rsa_err("Couldn't convert to a RSA style key");
+ ret = -EINVAL;
+ goto err_rsa;
+ }
+
+ EVP_PKEY_free(key);
+ *rsap = rsa;
+
+ return 0;
+
+err_rsa:
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key
+ *
+ * @keydir: Directory containing the key (PEM file) or key prefix (engine)
+ * @name Name of key
+ * @engine Engine to use for signing
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ if (engine)
+ return rsa_engine_get_priv_key(keydir, name, engine, rsap);
+ return rsa_pem_get_priv_key(keydir, name, rsap);
+}
+
+static int rsa_init(void)
+{
+ int ret;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+ ret = SSL_library_init();
+#else
+ ret = OPENSSL_init_ssl(0, NULL);
+#endif
+ if (!ret) {
+ fprintf(stderr, "Failure to init SSL library\n");
+ return -1;
+ }
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+ SSL_load_error_strings();
+
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_digests();
+ OpenSSL_add_all_ciphers();
+#endif
+
+ return 0;
+}
+
+static int rsa_engine_init(const char *engine_id, ENGINE **pe)
+{
+ ENGINE *e;
+ int ret;
+
+ ENGINE_load_builtin_engines();
+
+ e = ENGINE_by_id(engine_id);
+ if (!e) {
+ fprintf(stderr, "Engine isn't available\n");
+ ret = -1;
+ goto err_engine_by_id;
+ }
+
+ if (!ENGINE_init(e)) {
+ fprintf(stderr, "Couldn't initialize engine\n");
+ ret = -1;
+ goto err_engine_init;
+ }
+
+ if (!ENGINE_set_default_RSA(e)) {
+ fprintf(stderr, "Couldn't set engine as default for RSA\n");
+ ret = -1;
+ goto err_set_rsa;
+ }
+
+ *pe = e;
+
+ return 0;
+
+err_set_rsa:
+ ENGINE_finish(e);
+err_engine_init:
+ ENGINE_free(e);
+err_engine_by_id:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+ ENGINE_cleanup();
+#endif
+ return ret;
+}
+
+static void rsa_remove(void)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+ CRYPTO_cleanup_all_ex_data();
+ ERR_free_strings();
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+ ERR_remove_thread_state(NULL);
+#else
+ ERR_remove_state(0);
+#endif
+ EVP_cleanup();
+#endif
+}
+
+static void rsa_engine_remove(ENGINE *e)
+{
+ if (e) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ }
+}
+
+static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
+ struct checksum_algo *checksum_algo,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_size)
+{
+ EVP_PKEY *key;
+ EVP_PKEY_CTX *ckey;
+ EVP_MD_CTX *context;
+ int ret = 0;
+ size_t size;
+ uint8_t *sig;
+ int i;
+
+ key = EVP_PKEY_new();
+ if (!key)
+ return rsa_err("EVP_PKEY object creation failed");
+
+ if (!EVP_PKEY_set1_RSA(key, rsa)) {
+ ret = rsa_err("EVP key setup failed");
+ goto err_set;
+ }
+
+ size = EVP_PKEY_size(key);
+ sig = malloc(size);
+ if (!sig) {
+ fprintf(stderr, "Out of memory for signature (%zu bytes)\n",
+ size);
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ context = EVP_MD_CTX_create();
+ if (!context) {
+ ret = rsa_err("EVP context creation failed");
+ goto err_create;
+ }
+ EVP_MD_CTX_init(context);
+
+ ckey = EVP_PKEY_CTX_new(key, NULL);
+ if (!ckey) {
+ ret = rsa_err("EVP key context creation failed");
+ goto err_create;
+ }
+
+ if (EVP_DigestSignInit(context, &ckey,
+ checksum_algo->calculate_sign(),
+ NULL, key) <= 0) {
+ ret = rsa_err("Signer setup failed");
+ goto err_sign;
+ }
+
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+ if (padding_algo && !strcmp(padding_algo->name, "pss")) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ckey,
+ RSA_PKCS1_PSS_PADDING) <= 0) {
+ ret = rsa_err("Signer padding setup failed");
+ goto err_sign;
+ }
+ }
+#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
+
+ for (i = 0; i < region_count; i++) {
+ if (!EVP_DigestSignUpdate(context, region[i].data,
+ region[i].size)) {
+ ret = rsa_err("Signing data failed");
+ goto err_sign;
+ }
+ }
+
+ if (!EVP_DigestSignFinal(context, sig, &size)) {
+ ret = rsa_err("Could not obtain signature");
+ goto err_sign;
+ }
+
+ #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
+ EVP_MD_CTX_cleanup(context);
+ #else
+ EVP_MD_CTX_reset(context);
+ #endif
+ EVP_MD_CTX_destroy(context);
+ EVP_PKEY_free(key);
+
+ debug("Got signature: %d bytes, expected %zu\n", *sig_size, size);
+ *sigp = sig;
+ *sig_size = size;
+
+ return 0;
+
+err_sign:
+ EVP_MD_CTX_destroy(context);
+err_create:
+ free(sig);
+err_alloc:
+err_set:
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+int rsa_sign(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t **sigp, uint *sig_len)
+{
+ RSA *rsa;
+ ENGINE *e = NULL;
+ int ret;
+
+ ret = rsa_init();
+ if (ret)
+ return ret;
+
+ if (info->engine_id) {
+ ret = rsa_engine_init(info->engine_id, &e);
+ if (ret)
+ goto err_engine;
+ }
+
+ ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
+ if (ret)
+ goto err_priv;
+ ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
+ region_count, sigp, sig_len);
+ if (ret)
+ goto err_sign;
+
+ RSA_free(rsa);
+ if (info->engine_id)
+ rsa_engine_remove(e);
+ rsa_remove();
+
+ return ret;
+
+err_sign:
+ RSA_free(rsa);
+err_priv:
+ if (info->engine_id)
+ rsa_engine_remove(e);
+err_engine:
+ rsa_remove();
+ return ret;
+}
+
+/*
+ * rsa_get_exponent(): - Get the public exponent from an RSA key
+ */
+static int rsa_get_exponent(RSA *key, uint64_t *e)
+{
+ int ret;
+ BIGNUM *bn_te;
+ const BIGNUM *key_e;
+ uint64_t te;
+
+ ret = -EINVAL;
+ bn_te = NULL;
+
+ if (!e)
+ goto cleanup;
+
+ RSA_get0_key(key, NULL, &key_e, NULL);
+ if (BN_num_bits(key_e) > 64)
+ goto cleanup;
+
+ *e = BN_get_word(key_e);
+
+ if (BN_num_bits(key_e) < 33) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ bn_te = BN_dup(key_e);
+ if (!bn_te)
+ goto cleanup;
+
+ if (!BN_rshift(bn_te, bn_te, 32))
+ goto cleanup;
+
+ if (!BN_mask_bits(bn_te, 32))
+ goto cleanup;
+
+ te = BN_get_word(bn_te);
+ te <<= 32;
+ *e |= te;
+ ret = 0;
+
+cleanup:
+ if (bn_te)
+ BN_free(bn_te);
+
+ return ret;
+}
+
+/*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+ BIGNUM **modulusp, BIGNUM **r_squaredp)
+{
+ BIGNUM *big1, *big2, *big32, *big2_32;
+ BIGNUM *n, *r, *r_squared, *tmp;
+ const BIGNUM *key_n;
+ BN_CTX *bn_ctx = BN_CTX_new();
+ int ret = 0;
+
+ /* Initialize BIGNUMs */
+ big1 = BN_new();
+ big2 = BN_new();
+ big32 = BN_new();
+ r = BN_new();
+ r_squared = BN_new();
+ tmp = BN_new();
+ big2_32 = BN_new();
+ n = BN_new();
+ if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+ !n) {
+ fprintf(stderr, "Out of memory (bignum)\n");
+ return -ENOMEM;
+ }
+
+ if (0 != rsa_get_exponent(key, exponent))
+ ret = -1;
+
+ RSA_get0_key(key, &key_n, NULL, NULL);
+ if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) ||
+ !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
+ ret = -1;
+
+ /* big2_32 = 2^32 */
+ if (!BN_exp(big2_32, big2, big32, bn_ctx))
+ ret = -1;
+
+ /* Calculate n0_inv = -1 / n[0] mod 2^32 */
+ if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+ !BN_sub(tmp, big2_32, tmp))
+ ret = -1;
+ *n0_invp = BN_get_word(tmp);
+
+ /* Calculate R = 2^(# of key bits) */
+ if (!BN_set_word(tmp, BN_num_bits(n)) ||
+ !BN_exp(r, big2, tmp, bn_ctx))
+ ret = -1;
+
+ /* Calculate r_squared = R^2 mod n */
+ if (!BN_copy(r_squared, r) ||
+ !BN_mul(tmp, r_squared, r, bn_ctx) ||
+ !BN_mod(r_squared, tmp, n, bn_ctx))
+ ret = -1;
+
+ *modulusp = n;
+ *r_squaredp = r_squared;
+
+ BN_free(big1);
+ BN_free(big2);
+ BN_free(big32);
+ BN_free(r);
+ BN_free(tmp);
+ BN_free(big2_32);
+ if (ret) {
+ fprintf(stderr, "Bignum operations failed\n");
+ return -ENOMEM;
+ }
+
+ return ret;
+}
+
+static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
+ BIGNUM *num, int num_bits)
+{
+ int nwords = num_bits / 32;
+ int size;
+ uint32_t *buf, *ptr;
+ BIGNUM *tmp, *big2, *big32, *big2_32;
+ BN_CTX *ctx;
+ int ret;
+
+ tmp = BN_new();
+ big2 = BN_new();
+ big32 = BN_new();
+ big2_32 = BN_new();
+
+ /*
+ * Note: This code assumes that all of the above succeed, or all fail.
+ * In practice memory allocations generally do not fail (unless the
+ * process is killed), so it does not seem worth handling each of these
+ * as a separate case. Technicaly this could leak memory on failure,
+ * but a) it won't happen in practice, and b) it doesn't matter as we
+ * will immediately exit with a failure code.
+ */
+ if (!tmp || !big2 || !big32 || !big2_32) {
+ fprintf(stderr, "Out of memory (bignum)\n");
+ return -ENOMEM;
+ }
+ ctx = BN_CTX_new();
+ if (!tmp) {
+ fprintf(stderr, "Out of memory (bignum context)\n");
+ return -ENOMEM;
+ }
+ BN_set_word(big2, 2L);
+ BN_set_word(big32, 32L);
+ BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
+
+ size = nwords * sizeof(uint32_t);
+ buf = malloc(size);
+ if (!buf) {
+ fprintf(stderr, "Out of memory (%d bytes)\n", size);
+ return -ENOMEM;
+ }
+
+ /* Write out modulus as big endian array of integers */
+ for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
+ BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
+ *ptr = cpu_to_fdt32(BN_get_word(tmp));
+ BN_rshift(num, num, 32); /* N = N/B */
+ }
+
+ /*
+ * We try signing with successively increasing size values, so this
+ * might fail several times
+ */
+ ret = fdt_setprop(blob, noffset, prop_name, buf, size);
+ free(buf);
+ BN_free(tmp);
+ BN_free(big2);
+ BN_free(big32);
+ BN_free(big2_32);
+
+ return ret ? -FDT_ERR_NOSPACE : 0;
+}
+
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+{
+ BIGNUM *modulus, *r_squared;
+ uint64_t exponent;
+ uint32_t n0_inv;
+ int parent, node;
+ char name[100];
+ int ret;
+ int bits;
+ RSA *rsa;
+ ENGINE *e = NULL;
+
+ debug("%s: Getting verification data\n", __func__);
+ if (info->engine_id) {
+ ret = rsa_engine_init(info->engine_id, &e);
+ if (ret)
+ return ret;
+ }
+ ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
+ if (ret)
+ goto err_get_pub_key;
+ ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
+ if (ret)
+ goto err_get_params;
+ bits = BN_num_bits(modulus);
+ parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
+ if (parent == -FDT_ERR_NOTFOUND) {
+ parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
+ if (parent < 0) {
+ ret = parent;
+ if (ret != -FDT_ERR_NOSPACE) {
+ fprintf(stderr, "Couldn't create signature node: %s\n",
+ fdt_strerror(parent));
+ }
+ }
+ }
+ if (ret)
+ goto done;
+
+ /* Either create or overwrite the named key node */
+ snprintf(name, sizeof(name), "key-%s", info->keyname);
+ node = fdt_subnode_offset(keydest, parent, name);
+ if (node == -FDT_ERR_NOTFOUND) {
+ node = fdt_add_subnode(keydest, parent, name);
+ if (node < 0) {
+ ret = node;
+ if (ret != -FDT_ERR_NOSPACE) {
+ fprintf(stderr, "Could not create key subnode: %s\n",
+ fdt_strerror(node));
+ }
+ }
+ } else if (node < 0) {
+ fprintf(stderr, "Cannot select keys parent: %s\n",
+ fdt_strerror(node));
+ ret = node;
+ }
+
+ if (!ret) {
+ ret = fdt_setprop_string(keydest, node, "key-name-hint",
+ info->keyname);
+ }
+ if (!ret)
+ ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+ if (!ret)
+ ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
+ if (!ret) {
+ ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
+ }
+ if (!ret) {
+ ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
+ bits);
+ }
+ if (!ret) {
+ ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
+ bits);
+ }
+ if (!ret) {
+ ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
+ info->name);
+ }
+ if (!ret && info->require_keys) {
+ ret = fdt_setprop_string(keydest, node, "required",
+ info->require_keys);
+ }
+done:
+ BN_free(modulus);
+ BN_free(r_squared);
+ if (ret)
+ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+err_get_params:
+ RSA_free(rsa);
+err_get_pub_key:
+ if (info->engine_id)
+ rsa_engine_remove(e);
+
+ return ret;
+}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
new file mode 100644
index 00000000..82dc5132
--- /dev/null
+++ b/lib/rsa/rsa-verify.c
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Google Inc.
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <asm/types.h>
+#include <asm/unaligned.h>
+#include <dm.h>
+#else
+#include "fdt_host.h"
+#include "mkimage.h"
+#include <fdt_support.h>
+#endif
+#include <u-boot/rsa-mod-exp.h>
+#include <u-boot/rsa.h>
+
+/* Default public exponent for backward compatibility */
+#define RSA_DEFAULT_PUBEXP 65537
+
+/**
+ * rsa_verify_padding() - Verify RSA message padding is valid
+ *
+ * Verify a RSA message's padding is consistent with PKCS1.5
+ * padding as described in the RSA PKCS#1 v2.1 standard.
+ *
+ * @msg: Padded message
+ * @pad_len: Number of expected padding bytes
+ * @algo: Checksum algo structure having information on DER encoding etc.
+ * @return 0 on success, != 0 on failure
+ */
+static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
+ struct checksum_algo *algo)
+{
+ int ff_len;
+ int ret;
+
+ /* first byte must be 0x00 */
+ ret = *msg++;
+ /* second byte must be 0x01 */
+ ret |= *msg++ ^ 0x01;
+ /* next ff_len bytes must be 0xff */
+ ff_len = pad_len - algo->der_len - 3;
+ ret |= *msg ^ 0xff;
+ ret |= memcmp(msg, msg+1, ff_len-1);
+ msg += ff_len;
+ /* next byte must be 0x00 */
+ ret |= *msg++;
+ /* next der_len bytes must match der_prefix */
+ ret |= memcmp(msg, algo->der_prefix, algo->der_len);
+
+ return ret;
+}
+
+int padding_pkcs_15_verify(struct image_sign_info *info,
+ uint8_t *msg, int msg_len,
+ const uint8_t *hash, int hash_len)
+{
+ struct checksum_algo *checksum = info->checksum;
+ int ret, pad_len = msg_len - checksum->checksum_len;
+
+ /* Check pkcs1.5 padding bytes. */
+ ret = rsa_verify_padding(msg, pad_len, checksum);
+ if (ret) {
+ debug("In RSAVerify(): Padding check failed!\n");
+ return -EINVAL;
+ }
+
+ /* Check hash. */
+ if (memcmp((uint8_t *)msg + pad_len, hash, msg_len - pad_len)) {
+ debug("In RSAVerify(): Hash check failed!\n");
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+static void u32_i2osp(uint32_t val, uint8_t *buf)
+{
+ buf[0] = (uint8_t)((val >> 24) & 0xff);
+ buf[1] = (uint8_t)((val >> 16) & 0xff);
+ buf[2] = (uint8_t)((val >> 8) & 0xff);
+ buf[3] = (uint8_t)((val >> 0) & 0xff);
+}
+
+/**
+ * mask_generation_function1() - generate an octet string
+ *
+ * Generate an octet string used to check rsa signature.
+ * It use an input octet string and a hash function.
+ *
+ * @checksum: A Hash function
+ * @seed: Specifies an input variable octet string
+ * @seed_len: Size of the input octet string
+ * @output: Specifies the output octet string
+ * @output_len: Size of the output octet string
+ * @return 0 if the octet string was correctly generated, others on error
+ */
+static int mask_generation_function1(struct checksum_algo *checksum,
+ uint8_t *seed, int seed_len,
+ uint8_t *output, int output_len)
+{
+ struct image_region region[2];
+ int ret = 0, i, i_output = 0, region_count = 2;
+ uint32_t counter = 0;
+ uint8_t buf_counter[4], *tmp;
+ int hash_len = checksum->checksum_len;
+
+ memset(output, 0, output_len);
+
+ region[0].data = seed;
+ region[0].size = seed_len;
+ region[1].data = &buf_counter[0];
+ region[1].size = 4;
+
+ tmp = malloc(hash_len);
+ if (!tmp) {
+ debug("%s: can't allocate array tmp\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ while (i_output < output_len) {
+ u32_i2osp(counter, &buf_counter[0]);
+
+ ret = checksum->calculate(checksum->name,
+ region, region_count,
+ tmp);
+ if (ret < 0) {
+ debug("%s: Error in checksum calculation\n", __func__);
+ goto out;
+ }
+
+ i = 0;
+ while ((i_output < output_len) && (i < hash_len)) {
+ output[i_output] = tmp[i];
+ i_output++;
+ i++;
+ }
+
+ counter++;
+ }
+
+out:
+ free(tmp);
+
+ return ret;
+}
+
+static int compute_hash_prime(struct checksum_algo *checksum,
+ uint8_t *pad, int pad_len,
+ uint8_t *hash, int hash_len,
+ uint8_t *salt, int salt_len,
+ uint8_t *hprime)
+{
+ struct image_region region[3];
+ int ret, region_count = 3;
+
+ region[0].data = pad;
+ region[0].size = pad_len;
+ region[1].data = hash;
+ region[1].size = hash_len;
+ region[2].data = salt;
+ region[2].size = salt_len;
+
+ ret = checksum->calculate(checksum->name, region, region_count, hprime);
+ if (ret < 0) {
+ debug("%s: Error in checksum calculation\n", __func__);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int padding_pss_verify(struct image_sign_info *info,
+ uint8_t *msg, int msg_len,
+ const uint8_t *hash, int hash_len)
+{
+ uint8_t *masked_db = NULL;
+ int masked_db_len = msg_len - hash_len - 1;
+ uint8_t *h = NULL, *hprime = NULL;
+ int h_len = hash_len;
+ uint8_t *db_mask = NULL;
+ int db_mask_len = masked_db_len;
+ uint8_t *db = NULL, *salt = NULL;
+ int db_len = masked_db_len, salt_len = msg_len - hash_len - 2;
+ uint8_t pad_zero[8] = { 0 };
+ int ret, i, leftmost_bits = 1;
+ uint8_t leftmost_mask;
+ struct checksum_algo *checksum = info->checksum;
+
+ /* first, allocate everything */
+ masked_db = malloc(masked_db_len);
+ h = malloc(h_len);
+ db_mask = malloc(db_mask_len);
+ db = malloc(db_len);
+ salt = malloc(salt_len);
+ hprime = malloc(hash_len);
+ if (!masked_db || !h || !db_mask || !db || !salt || !hprime) {
+ printf("%s: can't allocate some buffer\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* step 4: check if the last byte is 0xbc */
+ if (msg[msg_len - 1] != 0xbc) {
+ printf("%s: invalid pss padding (0xbc is missing)\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* step 5 */
+ memcpy(masked_db, msg, masked_db_len);
+ memcpy(h, msg + masked_db_len, h_len);
+
+ /* step 6 */
+ leftmost_mask = (0xff >> (8 - leftmost_bits)) << (8 - leftmost_bits);
+ if (masked_db[0] & leftmost_mask) {
+ printf("%s: invalid pss padding ", __func__);
+ printf("(leftmost bit of maskedDB not zero)\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* step 7 */
+ mask_generation_function1(checksum, h, h_len, db_mask, db_mask_len);
+
+ /* step 8 */
+ for (i = 0; i < db_len; i++)
+ db[i] = masked_db[i] ^ db_mask[i];
+
+ /* step 9 */
+ db[0] &= 0xff >> leftmost_bits;
+
+ /* step 10 */
+ if (db[0] != 0x01) {
+ printf("%s: invalid pss padding ", __func__);
+ printf("(leftmost byte of db isn't 0x01)\n");
+ ret = EINVAL;
+ goto out;
+ }
+
+ /* step 11 */
+ memcpy(salt, &db[1], salt_len);
+
+ /* step 12 & 13 */
+ compute_hash_prime(checksum, pad_zero, 8,
+ (uint8_t *)hash, hash_len,
+ salt, salt_len, hprime);
+
+ /* step 14 */
+ ret = memcmp(h, hprime, hash_len);
+
+out:
+ free(hprime);
+ free(salt);
+ free(db);
+ free(db_mask);
+ free(h);
+ free(masked_db);
+
+ return ret;
+}
+#endif
+
+/**
+ * rsa_verify_key() - Verify a signature against some data using RSA Key
+ *
+ * Verify a RSA PKCS1.5 signature against an expected hash using
+ * the RSA Key properties in prop structure.
+ *
+ * @info: Specifies key and FIT information
+ * @prop: Specifies key
+ * @sig: Signature
+ * @sig_len: Number of bytes in signature
+ * @hash: Pointer to the expected hash
+ * @key_len: Number of bytes in rsa key
+ * @return 0 if verified, -ve on error
+ */
+static int rsa_verify_key(struct image_sign_info *info,
+ struct key_prop *prop, const uint8_t *sig,
+ const uint32_t sig_len, const uint8_t *hash,
+ const uint32_t key_len)
+{
+ int ret;
+#if !defined(USE_HOSTCC)
+ struct udevice *mod_exp_dev;
+#endif
+ struct checksum_algo *checksum = info->checksum;
+ struct padding_algo *padding = info->padding;
+ int hash_len;
+
+ if (!prop || !sig || !hash || !checksum)
+ return -EIO;
+
+ if (sig_len != (prop->num_bits / 8)) {
+ debug("Signature is of incorrect length %d\n", sig_len);
+ return -EINVAL;
+ }
+
+ debug("Checksum algorithm: %s", checksum->name);
+
+ /* Sanity check for stack size */
+ if (sig_len > RSA_MAX_SIG_BITS / 8) {
+ debug("Signature length %u exceeds maximum %d\n", sig_len,
+ RSA_MAX_SIG_BITS / 8);
+ return -EINVAL;
+ }
+
+ uint8_t buf[sig_len];
+ hash_len = checksum->checksum_len;
+
+#if !defined(USE_HOSTCC)
+ ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
+ if (ret) {
+ printf("RSA: Can't find Modular Exp implementation\n");
+ return -EINVAL;
+ }
+
+ ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
+#else
+ ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
+#endif
+ if (ret) {
+ debug("Error in Modular exponentation\n");
+ return ret;
+ }
+
+ ret = padding->verify(info, buf, key_len, hash, hash_len);
+ if (ret) {
+ debug("In RSAVerify(): padding check failed!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * rsa_verify_with_keynode() - Verify a signature against some data using
+ * information in node with prperties of RSA Key like modulus, exponent etc.
+ *
+ * Parse sign-node and fill a key_prop structure with properties of the
+ * key. Verify a RSA PKCS1.5 signature against an expected hash using
+ * the properties parsed
+ *
+ * @info: Specifies key and FIT information
+ * @hash: Pointer to the expected hash
+ * @sig: Signature
+ * @sig_len: Number of bytes in signature
+ * @node: Node having the RSA Key properties
+ * @return 0 if verified, -ve on error
+ */
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+ const void *hash, uint8_t *sig,
+ uint sig_len, int node)
+{
+ const void *blob = info->fdt_blob;
+ struct key_prop prop;
+ int length;
+ int ret = 0;
+
+ if (node < 0) {
+ debug("%s: Skipping invalid node", __func__);
+ return -EBADF;
+ }
+
+ prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
+
+ prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+
+ prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
+ if (!prop.public_exponent || length < sizeof(uint64_t))
+ prop.public_exponent = NULL;
+
+ prop.exp_len = sizeof(uint64_t);
+
+ prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
+
+ prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
+
+ if (!prop.num_bits || !prop.modulus) {
+ debug("%s: Missing RSA key info", __func__);
+ return -EFAULT;
+ }
+
+ ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
+ info->crypto->key_len);
+
+ return ret;
+}
+
+int rsa_verify(struct image_sign_info *info,
+ const struct image_region region[], int region_count,
+ uint8_t *sig, uint sig_len)
+{
+ const void *blob = info->fdt_blob;
+ /* Reserve memory for maximum checksum-length */
+ uint8_t hash[info->crypto->key_len];
+ int ndepth, noffset;
+ int sig_node, node;
+ char name[100];
+ int ret;
+
+ /*
+ * Verify that the checksum-length does not exceed the
+ * rsa-signature-length
+ */
+ if (info->checksum->checksum_len >
+ info->crypto->key_len) {
+ debug("%s: invlaid checksum-algorithm %s for %s\n",
+ __func__, info->checksum->name, info->crypto->name);
+ return -EINVAL;
+ }
+
+ sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+ if (sig_node < 0) {
+ debug("%s: No signature node found\n", __func__);
+ return -ENOENT;
+ }
+
+ /* Calculate checksum with checksum-algorithm */
+ ret = info->checksum->calculate(info->checksum->name,
+ region, region_count, hash);
+ if (ret < 0) {
+ debug("%s: Error in checksum calculation\n", __func__);
+ return -EINVAL;
+ }
+
+ /* See if we must use a particular key */
+ if (info->required_keynode != -1) {
+ ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+ info->required_keynode);
+ return ret;
+ }
+
+ /* Look for a key that matches our hint */
+ snprintf(name, sizeof(name), "key-%s", info->keyname);
+ node = fdt_subnode_offset(blob, sig_node, name);
+ ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+ if (!ret)
+ return ret;
+
+ /* No luck, so try each of the keys in turn */
+ for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
+ (noffset >= 0) && (ndepth > 0);
+ noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+ if (ndepth == 1 && noffset != node) {
+ ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+ noffset);
+ if (!ret)
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/lib/sec_library/include/aes.h b/lib/sec_library/include/aes.h
new file mode 100644
index 00000000..ea90660a
--- /dev/null
+++ b/lib/sec_library/include/aes.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/aes.h
+ * @brief Header File for AES Driver
+ * @version V1.0
+ * @date 9. Oct 2020
+ * @model aes
+ ******************************************************************************/
+
+#ifndef _DRV_AES_H_
+#define _DRV_AES_H_
+
+#include <stdint.h>
+#include <drv/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----- Encrypt & Decrypt: Config key length -----*/
+typedef enum {
+ AES_KEY_LEN_BITS_128 = 0, ///< 128 Data bits
+ AES_KEY_LEN_BITS_192, ///< 192 Data bits
+ AES_KEY_LEN_BITS_256 ///< 256 Data bits
+} csi_aes_key_bits_t;
+
+/**
+\brief AES Ctrl Block
+*/
+typedef struct {
+ csi_dev_t dev;
+ void *priv;
+} csi_aes_t;
+
+/**
+ \brief Initialize AES interface. Initializes the resources needed for the AES interface
+ \param[in] aes Handle to operate
+ \param[in] idx Device id
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_init(csi_aes_t *aes, uint32_t idx);
+
+/**
+ \brief De-initialize AES interface. Stops operation and releases the software resources used by the interface
+ \param[in] aes Dandle to operate
+ \return None
+*/
+void csi_aes_uninit(csi_aes_t *aes);
+
+/**
+ \brief Set encrypt key
+ \param[in] aes Handle to operate
+ \param[in] key Pointer to the key buf
+ \param[in] key_len Pointer to \ref csi_aes_key_bits_t
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_set_encrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len);
+
+/**
+ \brief Set decrypt key
+ \param[in] aes Handle to operate
+ \param[in] key Pointer to the key buf
+ \param[in] key_len Pointer to \ref csi_aes_key_bits_t
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_set_decrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len);
+
+/**
+ \brief AES ecb encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_ecb_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size);
+
+/**
+ \brief AES ecb decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_ecb_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size);
+
+/**
+ \brief AES cbc encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cbc_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cbc decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cbc_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cfb1 encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cfb1_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cfb1 decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cfb1_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cfb8 encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cfb8_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cfb8 decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \return Error code \ref Csi_error_t
+*/
+csi_error_t csi_aes_cfb8_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief AES cfb128 decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_cfb128_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num);
+
+/**
+ \brief AES cfb128 encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_cfb128_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num);
+
+/**
+ \brief AES ofb encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_ofb_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num);
+
+/**
+ \brief AES ofb decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] iv Init vector
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_ofb_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num);
+
+/**
+ \brief AES ctr encrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] nonce_counter Pointer to the 128-bit nonce and counter
+ \param[in] stream_block Pointer to the saved stream-block for resuming
+ \param[in] iv Init vector
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_ctr_encrypt(csi_aes_t *aes,
+ void *in,
+ void *out,
+ uint32_t size,
+ uint8_t nonce_counter[16],
+ uint8_t stream_block[16],
+ void *iv,
+ uint32_t *num);
+
+/**
+ \brief AES ctr decrypt
+ \param[in] aes Handle to operate
+ \param[in] in Pointer to the source data
+ \param[out] out Pointer to the result data
+ \param[in] size The source data size
+ \param[in] nonce_counter Pointer to the 128-bit nonce and counter
+ \param[in] stream_block Pointer to the saved stream-block for resuming
+ \param[in] iv Init vecotr
+ \param[out] num The number of the 128-bit block we have used
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_ctr_decrypt(csi_aes_t *aes,
+ void *in,
+ void *out,
+ uint32_t size,
+ uint8_t nonce_counter[16],
+ uint8_t stream_block[16],
+ void *iv,
+ uint32_t *num);
+
+/**
+ \brief Enable AES power manage
+ \param[in] aes Handle to operate
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_aes_enable_pm(csi_aes_t *aes);
+
+/**
+ \brief Disable AES power manage
+ \param[in] aes Handle to operate
+ \return None
+*/
+void csi_aes_disable_pm(csi_aes_t *aes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRV_AES_H_ */
diff --git a/lib/sec_library/include/csi_efuse_api.h b/lib/sec_library/include/csi_efuse_api.h
new file mode 100644
index 00000000..748a7b06
--- /dev/null
+++ b/lib/sec_library/include/csi_efuse_api.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019-2021 Alibaba Group Holding Limited
+ */
+#ifndef __CSI_EFUSE_API_H__
+#define __CSI_EFUSE_API_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SECURE_BOOT_DIS = 0x5a5a5a5a,
+ SECURE_BOOT_EN = ~(SECURE_BOOT_DIS),
+} sboot_st_t;
+
+
+typedef enum {
+ IMAGE_ENCRYPT_DIS = 0x5a5a5a5a,
+ IMAGE_ENCRYPT_EN = ~(IMAGE_ENCRYPT_DIS),
+} img_encrypt_st_t;
+
+int csi_efuse_api_int(void);
+
+int csi_efuse_api_uninit(void);
+
+int csi_efuse_get_secure_boot_st(sboot_st_t *sboot_st);
+
+int csi_efuse_get_digest_signature_scheme(uint32_t *digest_scheme, uint32_t *signature_scheme);
+
+int csi_efuse_get_bl2_encrypt_st(img_encrypt_st_t *encrypt_st);
+
+int csi_efuse_set_bl2_encrypt_st(img_encrypt_st_t encrypt_st);
+
+int csi_efuse_get_bl3_encrypt_st(img_encrypt_st_t *encrypt_st);
+
+int csi_efuse_set_bl3_encrypt_st(img_encrypt_st_t encrypt_st);
+
+int csi_efuse_get_bl1_version(uint32_t *version);
+
+int csi_efuse_set_bl1_version(uint32_t version);
+
+int csi_efuse_get_bl2_version(uint32_t *version);
+
+int csi_efuse_set_bl2_version(uint32_t version);
+
+int csi_efuse_read_raw(uint32_t addr, void *data, uint32_t cnt);
+
+int csi_efuse_write_raw(uint32_t addr, const void *data, uint32_t cnt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CSI_EFUSE_API_H__ */
diff --git a/lib/sec_library/include/csi_sec_img_verify.h b/lib/sec_library/include/csi_sec_img_verify.h
new file mode 100644
index 00000000..24190684
--- /dev/null
+++ b/lib/sec_library/include/csi_sec_img_verify.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019-2021 Alibaba Group Holding Limited
+ */
+#ifndef __CSI_SEC_IMG_VERIFY_H__
+#define __CSI_SEC_IMG_VERIFY_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ BOOT_STAGE_BL1 = 0,
+ BOOT_STAGE_BL2,
+ BOOT_STAGE_ERR,
+} boot_stage_t;
+
+int csi_sec_custom_image_verify(unsigned long img_src_addr, unsigned long cur_hdr_addr);
+
+int csi_sec_uboot_image_verify(unsigned long img_src_addr, unsigned long cur_hdr_addr);
+
+int csi_sec_set_boot_stage(boot_stage_t boot_stage);
+
+int csi_sec_get_lib_version(char ** p_version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CSI_SEC_IMG_VERIFY_H__ */
diff --git a/lib/sec_library/include/kdf.h b/lib/sec_library/include/kdf.h
new file mode 100644
index 00000000..c07adedc
--- /dev/null
+++ b/lib/sec_library/include/kdf.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019-2021 Alibaba Group Holding Limited
+ */
+
+#ifndef __KDF_H__
+#define __KDF_H__
+#include "drv/aes.h"
+#include "drv/sm4.h"
+#include "drv/common.h"
+#include <stdint.h>
+
+typedef enum {
+ KDF_ROOT_CV_UNIQUE_KEY,
+ KDF_ROOT_CV_COMMON_KEY,
+ KDF_ROOT_USER_UNIQUE_KEY,
+ KDF_ROOT_USER_COMMON_KEY,
+ KDF_ROOT_KEY_MAX,
+} csi_kdf_root_key_t;
+
+typedef enum {
+ KDF_DERIVED_DFT_CHALLENGE_EK,
+ KDF_DERIVED_C910TJTAG_CHALLENGE_EK,
+ KDF_DERIVED_E902JTAG_CHALLENGE_EK,
+ KDF_DERIVED_IMAGE_EK,
+ KDF_DERIVED_SECURE_STORAGE_EK1,
+ KDF_DERIVED_SECURE_STORAGE_EK2,
+ KDF_DERIVED_SECURE_STORAGE_EK3,
+ KDF_DERIVED_SECURE_STORAGE_EK4,
+ KDF_DERIVED_SECURE_STORAGE_EK5,
+ KDF_DERIVED_SECURE_STORAGE_EK6,
+ KDF_DERIVED_SECURE_STORAGE_EK7,
+ KDF_DERIVED_SECURE_STORAGE_EK8,
+ KDF_DERIVED_SECURE_STORAGE_EK9,
+ KDF_DERIVED_SECURE_STORAGE_EK10,
+ KDF_DERIVED_SECURE_STORAGE_EK11,
+ KDF_DERIVED_SECURE_STORAGE_EK12,
+ KDF_DERIVED_SECURE_STORAGE_EK13,
+ KDF_DERIVED_SECURE_STORAGE_EK14,
+ KDF_DERIVED_SECURE_STORAGE_EK15,
+ KDF_DERIVED_SECURE_STORAGE_EK16,
+ KDF_DERIVED_RPMB_ACCESS_EK,
+ KDF_DERIVED_MAX,
+} csi_kdf_derived_key_t;
+
+typedef enum {
+ KDF_KEY_TYPE_AES_256,
+ KDF_KEY_TYPE_AES_192,
+ KDF_KEY_TYPE_AES_128,
+ KDF_KEY_TYPE_SM4,
+ KDF_KEY_TYPE_TDES_192,
+ KDF_KEY_TYPE_TDES_128,
+ KDF_KEY_TYPE_DES,
+ KDF_KEY_TYPE_MAX,
+} csi_kdf_key_type_t;
+
+typedef struct key_attr_tag {
+ uint8_t len_in_byte;
+ uint8_t valid;
+ uint32_t offset;
+} csi_kdf_key_attr_t;
+
+/**
+\brief KDF Ctrl Block
+*/
+typedef struct {
+ union {
+ csi_aes_t *aes;
+ csi_sm4_t *sm4;
+ };
+ csi_kdf_key_type_t type;
+} csi_kdf_key_handle_t;
+
+/**
+\brief KDF Ctrl Block
+*/
+typedef struct {
+ csi_dev_t dev;
+ void *priv;
+} csi_kdf_t;
+
+/**
+ \brief kdf initialiez.
+ \param[in] kdf Handle to operate.
+ \param[in] idx Device id.
+ \return error code
+*/
+csi_error_t csi_kdf_init(csi_kdf_t *kdf, uint32_t idx);
+
+/**
+ \brief kdf uninitialiez.
+ \param[in] kdf Handle to operate
+*/
+void csi_kdf_uninit(csi_kdf_t *kdf);
+
+/**
+ \brief Derive key function.
+ \param[in] kdf Handle to operate.
+ \param[in] rkey derive source root key type.
+ \param[in] dkey derived key type from root key.
+ \return error code
+*/
+csi_error_t csi_kdf_derived_key(csi_kdf_t *kdf, csi_kdf_root_key_t rkey,
+ csi_kdf_derived_key_t dkey);
+
+/**
+ \brief Destroy derived key in storage.
+ \param[in] kdf Handle to operate.
+ \param[in] dkey derived key type.
+ \return error code
+*/
+csi_error_t csi_kdf_destory_key(csi_kdf_t *kdf, csi_kdf_derived_key_t dkey);
+// xiaoxia: keyram layout config macro
+
+/**
+ \brief Set key to algorithim engine.
+ \param[in] handle Handle to cipher.
+ \param[in] kdf Handle to operate.
+ \param[in] dkey derived key type.
+ \return error code
+*/
+csi_error_t csi_kdf_set_key(csi_kdf_key_handle_t *handle, csi_kdf_t *kdf,
+ csi_kdf_derived_key_t dkey);
+
+/**
+ \brief Clear key in algorithim engine.
+ \param[in] kdf Handle to operate.
+ \param[in] dkey derived key type.
+ \return error code
+*/
+csi_error_t csi_kdf_clear_key(csi_kdf_t *kdf, csi_kdf_derived_key_t dkey);
+
+/**
+ \brief Get key attribute.
+ \param[in] kdf Handle to operate.
+ \param[in] dkey derived key type.
+ \param[out] attr Buffer to get attribute.
+ \return error code
+*/
+csi_error_t csi_kdf_get_key_attr(csi_kdf_t *kdf, csi_kdf_derived_key_t dkey,
+ csi_kdf_key_attr_t *attr);
+
+#endif
diff --git a/lib/sec_library/include/keyram.h b/lib/sec_library/include/keyram.h
new file mode 100644
index 00000000..6f8f706a
--- /dev/null
+++ b/lib/sec_library/include/keyram.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file keyram.h
+ * @brief CSI Source File for kdf Driver
+ * @version V1.0
+ * @date 12. MAR 2021
+ ******************************************************************************/
+
+#include "drv/kdf.h"
+#include <stdio.h>
+#include <string.h>
+
+#define KDF_CON 0x000
+#define KDF_KEYTRANSFER 0x004
+#define KDF_KEYINDEX 0x008
+#define KDF_INTCON 0x00C
+#define KDF_ZONE1SADDR 0x020
+#define KDF_ZONE2SADDR 0x030
+#define KDF_ZONE3SADDR 0x040
+#define KDF_RAMENC_KEY0H 0x058
+#define KDF_RAMENC_KEY0L 0x05c
+#define KDF_RAMENC_KEY1H 0x060
+#define KDF_RAMENC_KEY1L 0x064
+#define KDF_RAMENC_KEY2H 0x068
+#define KDF_RAMENC_KEY2L 0x06c
+#define KDF_RAMENC_KEY3H 0x070
+#define KDF_RAMENC_KEY3L 0x074
+#define KDF_MASK_RNG0 0x080
+#define KDF_MASK_RNG1 0x084
+#define KDF_MASK_RNG2 0x088
+#define KDF_MASK_RNG3 0x08c
+#define KDF_MASK_RNG4 0x090
+#define KDF_MASK_RNG5 0x094
+#define KDF_MASK_RNG6 0x098
+#define KDF_MASK_RNG7 0x09c
+#define KDF_STA 0x0a0
+#define KDF_IPID 0x0fc
+#define KDF_RAM 0x8000
+
+/**
+ * @brief keyram init.
+ *
+ * @return uint32_t
+ */
+uint32_t keyram_init();
+
+/**
+ * @brief keyram set key.
+ *
+ * @param key
+ * @param len
+ * @return uint32_t
+ */
+uint32_t keyram_set_key(csi_kdf_derived_key_t key, uint32_t len);
+
+/**
+ * @brief get key addr in keyram.
+ *
+ * @param key
+ * @param addr
+ * @return uint32_t
+ */
+uint32_t keyram_get_key_addr(csi_kdf_derived_key_t key, uint64_t *addr);
+
+/**
+ * @brief Clear key in keyram.
+ *
+ * @return uint32_t
+ */
+uint32_t keyram_clear();
+
+/**
+ * @brief Uninit. This function will lock KDF.
+ */
+void keyram_uninit();
diff --git a/lib/sec_library/include/rng.h b/lib/sec_library/include/rng.h
new file mode 100644
index 00000000..55fe37b1
--- /dev/null
+++ b/lib/sec_library/include/rng.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/tng.h
+ * @brief Header File for RNG Driver
+ * @version V1.0
+ * @date 22. Apr 2020
+ * @model tng
+ ******************************************************************************/
+#ifndef _DRV_TNG_H_
+#define _DRV_TNG_H_
+
+#include "drv/common.h"
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ \brief Get data from the TNG engine
+ \param[out] Data Pointer to buffer with data get from TNG
+ \param[in] Num Number of data items,uinit in uint32
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rng_get_multi_word(uint32_t *data, uint32_t num);
+
+/**
+ \brief Get data from the TNG engine
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rng_get_single_word(uint32_t* data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRV_TNG_H_ */
diff --git a/lib/sec_library/include/rsa.h b/lib/sec_library/include/rsa.h
new file mode 100644
index 00000000..5c2e53fc
--- /dev/null
+++ b/lib/sec_library/include/rsa.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file drv/rsa.h
+ * @brief Header File for RSA Driver
+ * @version V1.0
+ * @date 02. June 2020
+ * @model rsa
+ ******************************************************************************/
+#ifndef _DRV_RSA_H_
+#define _DRV_RSA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <drv/common.h>
+
+/*----- RSA Control Codes: Mode Parameters: Key Bits -----*/
+typedef enum {
+ RSA_KEY_BITS_192 = 0, ///< 192 Key bits
+ RSA_KEY_BITS_256, ///< 256 Key bits
+ RSA_KEY_BITS_512, ///< 512 Key bits
+ RSA_KEY_BITS_1024, ///< 1024 Key bits
+ RSA_KEY_BITS_2048, ///< 2048 Key bits
+ RSA_KEY_BITS_3072, ///< 3072 Key bits
+ RSA_KEY_BITS_4096 ///< 4096 Key bits
+} csi_rsa_key_bits_t;
+
+typedef enum {
+ RSA_PADDING_MODE_NO = 0, ///< RSA NO Padding Mode
+ RSA_PADDING_MODE_PKCS1, ///< RSA PKCS1 Padding Mode
+ RSA_PADDING_MODE_PKCS1_OAEP, ///< RSA PKCS1 OAEP Padding Mode
+ RSA_PADDING_MODE_SSLV23, ///< RSA SSLV23 Padding Mode
+ RSA_PADDING_MODE_X931, ///< RSA X931 Padding Mode
+ RSA_PADDING_MODE_PSS ///< RSA PSS Padding Mode
+} csi_rsa_padding_type_t;
+
+typedef enum {
+ RSA_HASH_TYPE_MD5 = 0,
+ RSA_HASH_TYPE_SHA1,
+ RSA_HASH_TYPE_SHA224,
+ RSA_HASH_TYPE_SHA256,
+ RSA_HASH_TYPE_SHA384,
+ RSA_HASH_TYPE_SHA512
+} csi_rsa_hash_type_t;
+
+typedef struct {
+ void *n; ///< Pointer to the public modulus
+ void *e; ///< Pointer to the public exponent
+ void *d; ///< Pointer to the private exponent
+ csi_rsa_key_bits_t key_bits; ///< RSA KEY BITS
+ csi_rsa_padding_type_t padding_type; ///< RSA PADDING TYPE
+} csi_rsa_context_t;
+
+/**
+\brief RSA State
+*/
+typedef struct {
+ uint8_t busy : 1; ///< Calculate busy flag
+ uint8_t error : 1; ///< Calculate error flag
+} csi_rsa_state_t;
+
+typedef struct {
+ csi_dev_t dev;
+ void *cb;
+ void *arg;
+ csi_rsa_state_t state;
+ void *prim;
+} csi_rsa_t;
+
+typedef struct {
+ uint32_t pout[64];
+ uint8_t *pouts;
+ uint32_t *pout_size;
+ uint32_t u32keywords;
+ uint8_t *pdst;
+ uint32_t u32padding;
+ uint32_t u32dst_words;
+ uint32_t u32type;
+ uint32_t rsa_state;
+}rsa_middle_t;
+
+/****** RSA Event *****/
+typedef enum {
+ RSA_EVENT_COMPLETE = 0, ///< rsa event completed
+ RSA_EVENT_VERIFY_SUCCESS,
+ RSA_EVENT_VERIFY_FAILED,
+ RSA_EVENT_ERROR, ///< error event
+} csi_rsa_event_t;
+
+typedef void (*csi_rsa_callback_t)(csi_rsa_t *rsa, csi_rsa_event_t event, void *arg); ///< Pointer to \ref csi_rsa_callback_t : RSA Event call back.
+
+/**
+ \brief Initialize RSA Interface. 1. Initializes the resources needed for the RSA interface 2.registers event callback function
+ \param[in] rsa RSA handle to operate.
+ \param[in] idx Device id
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_init(csi_rsa_t *rsa, uint32_t idx);
+
+/**
+ \brief De-initialize RSA Interface. stops operation and releases the software resources used by the interface
+ \param[in] rsa RSA handle to operate.
+ \return none
+*/
+void csi_rsa_uninit(csi_rsa_t *rsa);
+
+/**
+ \brief Attach the callback handler to RSA
+ \param[in] rsa Operate handle.
+ \param[in] cb Callback function
+ \param[in] arg User can define it by himself as callback's param
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_attach_callback(csi_rsa_t *rsa, csi_rsa_callback_t cb, void *arg);
+
+/**
+ \brief Detach the callback handler
+ \param[in] rsa Operate handle.
+*/
+void csi_rsa_detach_callback(csi_rsa_t *rsa);
+
+/**
+ \brief Generate rsa key pair.
+ \param[in] rsa RSA handle to operate.
+ \param[out] context Pointer to the rsa context
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_gen_key(csi_rsa_t *rsa, csi_rsa_context_t *context);
+
+/**
+ \brief Encrypt
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] out Pointer to the result buffer
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_encrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out);
+
+/**
+ \brief decrypt
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] out Pointer to the result buffer
+ \param[out] out_size The result size
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_decrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out, uint32_t *out_size);
+
+/**
+ \brief RSA sign
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] signature Pointer to the signature
+ \param[in] hash_type The source data hash type
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_sign(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, csi_rsa_hash_type_t hash_type);
+
+/**
+ \brief RSA verify
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[in] signature Pointer to the signature
+ \param[in] sig_size The signature size
+ \param[in] hash_type The source data hash type
+ \return Verify result
+*/
+bool csi_rsa_verify(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, uint32_t sig_size, csi_rsa_hash_type_t hash_type);
+
+/**
+ \brief encrypt(async mode)
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] out Pointer to the result buffer
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_encrypt_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out);
+
+/**
+ \brief decrypt(async mode)
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] out Pointer to the result buffer
+ \param[out] out_size The result size
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_decrypt_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out, uint32_t *out_size);
+
+/**
+ \brief RSA sign(async mode)
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[out] signature Pointer to the signature
+ \param[in] hash_type The source data hash type
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_sign_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, csi_rsa_hash_type_t hash_type);
+
+/**
+ \brief RSA verify(async mode)
+ \param[in] rsa RSA handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size The source data len
+ \param[in] signature Pointer to the signature
+ \param[in] sig_size The signature size
+ \param[in] hash_type The source data hash type
+ \return Verify result
+*/
+csi_error_t csi_rsa_verify_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, uint32_t sig_size, csi_rsa_hash_type_t hash_type);
+
+/**
+ \brief Get RSA state.
+ \param[in] rsa RSA handle to operate.
+ \param[out] state RSA state \ref csi_rsa_state_t.
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_get_state(csi_rsa_t *rsa, csi_rsa_state_t *state);
+
+/**
+ \brief Get big prime data
+ \param[in] rsa RSA handle to operate.
+ \param[in] p Pointer to the prime
+ \param[in] bit_length Pointer to the prime bit length
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_get_prime(csi_rsa_t *rsa, void *p, uint32_t bit_length);
+
+/**
+ \brief Enable rsa power manage
+ \param[in] rsa RSA handle to operate.
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_rsa_enable_pm(csi_rsa_t *rsa);
+
+/**
+ \brief Disable rsa power manage
+ \param[in] rsa RSA handle to operate.
+*/
+void csi_rsa_disable_pm(csi_rsa_t *rsa);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRV_RSA_H_ */
diff --git a/lib/sec_library/include/sec_crypto_aes.h b/lib/sec_library/include/sec_crypto_aes.h
new file mode 100755
index 00000000..47c45c05
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_aes.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file seccrypt_aes.h
+ * @brief Header File for AES
+ * @version V1.0
+ * @date 20. Jul 2020
+ * @model aes
+ ******************************************************************************/
+#ifndef _SC_AES_H_
+#define _SC_AES_H_
+
+#include <stdint.h>
+#include <sec_crypto_errcode.h>
+
+#ifdef CONFIG_SYSTEM_SECURE
+#include "drv/aes.h"
+#endif
+
+#ifdef CONFIG_SEC_CRYPTO_AES_SW
+#include "crypto_aes.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SC_AES_KEY_LEN_BITS_128 = 0U, ///< 128 Data bits
+ SC_AES_KEY_LEN_BITS_192, ///< 192 Data bits
+ SC_AES_KEY_LEN_BITS_256 ///< 256 Data bits
+} sc_aes_key_bits_t;
+
+/**
+\brief AES Ctrl Block
+*/
+typedef struct {
+#ifdef CONFIG_SYSTEM_SECURE
+#ifdef CONFIG_CSI_V1
+ aes_handle_t handle;
+ unsigned char key[32];
+ unsigned int key_len;
+#endif
+#ifdef CONFIG_CSI_V2
+ csi_aes_t csi_aes;
+ //unsigned char sc_ctx[SC_AES_CTX_SIZE];
+#endif
+#endif
+#if defined(CONFIG_TEE_CA)
+ unsigned char key[32];
+ unsigned int key_len;
+#endif
+#if defined(CONFIG_SEC_CRYPTO_AES_SW)
+ sc_mbedtls_aes_context aes_ctx;
+#endif
+ //void *ctx;
+} sc_aes_t;
+
+// Function documentation
+/**
+ \brief Initialize AES Interface. Initializes the resources needed for the AES interface
+ \param[in] aes operate handle
+ \param[in] idx device id
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_init(sc_aes_t *aes, uint32_t idx);
+
+/**
+ \brief De-initialize AES Interface. stops operation and releases the software resources used by the interface
+ \param[in] aes handle to operate
+ \return None
+*/
+void sc_aes_uninit(sc_aes_t *aes);
+
+/**
+ \brief Set encrypt key
+ \param[in] aes handle to operate
+ \param[in] key Pointer to the key buf
+ \param[in] key_len Pointer to \ref sc_aes_key_bits_t
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_set_encrypt_key(sc_aes_t *aes, void *key, sc_aes_key_bits_t key_len);
+
+/**
+ \brief Set decrypt key
+ \param[in] aes handle to operate
+ \param[in] key Pointer to the key buf
+ \param[in] key_len Pointer to \ref sc_aes_key_bits_t
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_set_decrypt_key(sc_aes_t *aes, void *key, sc_aes_key_bits_t key_len);
+
+/**
+ \brief Aes ecb encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ecb_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size);
+
+/**
+ \brief Aes ecb decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ecb_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size);
+
+/**
+ \brief Aes cbc encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cbc_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cbc decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cbc_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cfb1 encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb1_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cfb1 decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb1_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cfb8 encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb8_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cfb8 decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb8_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv);
+
+/**
+ \brief Aes cfb128 decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb128_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv,
+ uint32_t *num);
+
+/**
+ \brief Aes cfb128 encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_cfb128_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv,
+ uint32_t *num);
+/**
+ \brief Aes ofb encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ofb_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv,
+ uint32_t *num);
+/**
+ \brief Aes ofb decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ofb_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv,
+ uint32_t *num);
+/**
+ \brief Aes ctr encrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter Pointer to the 128-bit nonce and counter
+ \param[in] stream_block Pointer to the saved stream-block for resuming
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ctr_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size,
+ uint8_t nonce_counter[16], uint8_t stream_block[16], void *iv,
+ uint32_t *num);
+/**
+ \brief Aes ctr decrypt
+ \param[in] aes handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter Pointer to the 128-bit nonce and counter
+ \param[in] stream_block Pointer to the saved stream-block for resuming
+ \param[in] iv init vecotr
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_aes_ctr_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size,
+ uint8_t nonce_counter[16], uint8_t stream_block[16], void *iv,
+ uint32_t *num);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SC_AES_H_ */
diff --git a/lib/sec_library/include/sec_crypto_common.h b/lib/sec_library/include/sec_crypto_common.h
new file mode 100644
index 00000000..ad5ac4ff
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_common.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019-2021 Alibaba Group Holding Limited
+ */
+
+
+#ifndef __SEC_CRYPTO_COMMON_H__
+#define __SEC_CRYPTO_COMMON_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "rambus.h"
+#include "sec_crypto_errcode.h"
+#include "sec_crypto_aes.h"
+#include "sec_crypto_rng.h"
+#include "sec_crypto_rsa.h"
+#include "sec_crypto_sha.h"
+#include "sec_crypto_sm2.h"
+#include "sec_crypto_sm4.h"
+
+#define SC_lOG(...)
+
+#endif
+
diff --git a/lib/sec_library/include/sec_crypto_errcode.h b/lib/sec_library/include/sec_crypto_errcode.h
new file mode 100755
index 00000000..04b2e561
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_errcode.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019-2021 Alibaba Group Holding Limited
+ */
+
+#ifndef _SC_ERRCODE_H
+#define _SC_ERRCODE_H
+
+/* common */
+
+#ifndef SC_OK
+#define SC_ERROR_BASE 0x10000000
+#define SC_OK 0
+#define SC_FAIL SC_ERROR_BASE + 1
+#define SC_MEM_OVERFLOW SC_ERROR_BASE + 2
+#define SC_PARAM_INV SC_ERROR_BASE + 3
+#define SC_OPERATION_BUSY SC_ERROR_BASE + 4
+#define SC_AUTH_FAIL SC_ERROR_BASE + 5
+#define SC_CRYPT_FAIL SC_ERROR_BASE + 6
+#define SC_NOT_SUPPORT SC_ERROR_BASE + 7
+#define SC_INVALID_PADDING SC_ERROR_BASE + 8
+#define SC_BAD_INPUT_DATA SC_ERROR_BASE + 9
+#define SC_INVALID_KEY_LENGTH SC_ERROR_BASE + 10
+#define SC_INVALID_INPUT_LENGTH SC_ERROR_BASE + 11
+#define SC_FEATURE_UNAVAILABLE SC_ERROR_BASE + 12
+#define SC_HW_ACCEL_FAILED SC_ERROR_BASE + 13
+#define SC_CCM_AUTH_FAILED SC_ERROR_BASE + 14
+#define SC_KEY_GEN_FAILED SC_ERROR_BASE + 15
+#define SC_KEY_CHECK_FAILED SC_ERROR_BASE + 16
+#define SC_PUBLIC_FAILED SC_ERROR_BASE + 17
+#define SC_PRIVATE_FAILED SC_ERROR_BASE + 18
+#define SC_VERIFY_FAILED SC_ERROR_BASE + 19
+#define SC_OUTPUT_TOO_LARGE SC_ERROR_BASE + 20
+#define SC_RNG_FAILED SC_ERROR_BASE + 21
+#define SC_BUFFER_TOO_SMALL SC_ERROR_BASE + 22
+#define SC_INVALID_FORMAT SC_ERROR_BASE + 23
+#define SC_ALLOC_FAILED SC_ERROR_BASE + 24
+#define SC_DRV_FAILED SC_ERROR_BASE + 25
+
+#define CHECK_RET(x) \
+ do { \
+ if (!(x)) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_RET_WITH_RET(x, ret) \
+ do { \
+ if (!(x)) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return ret; \
+ } \
+ } while (0)
+
+#define CHECK_16byte_ALIGNMENT(_i, ret) \
+ if ((((uint64_t)_i) & 0xF) != 0) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return ret; \
+ }
+
+#define CHECK_32byte_ALIGNMENT(_i, ret) \
+ if ((((uint64_t)_i) & 0x1F) != 0) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return ret; \
+ }
+
+#define CHECK_64byte_ALIGNMENT(_i, ret) \
+ if ((((uint64_t)_i) & 0x3F) != 0) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return ret; \
+ }
+
+#define CHECK_PARAM_RET(c, r) \
+ do { \
+ if (!(c)) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return (r); \
+ } \
+ } while (0)
+
+#define CHECK_RET_VOID(c) \
+ do { \
+ if (!(c)) { \
+ LOG_CRIT("err %s, %d\n", __FUNCTION__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_PARAM CHECK_PARAM_RET
+#endif
+
+#endif
diff --git a/lib/sec_library/include/sec_crypto_rng.h b/lib/sec_library/include/sec_crypto_rng.h
new file mode 100755
index 00000000..4832c882
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_rng.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file seccrypt_rng.h
+ * @brief Header File for RNG
+ * @version V1.0
+ * @date 20. Jul 2020
+ * @model rng
+ ******************************************************************************/
+#ifndef _SC_RNG_H_
+#define _SC_RNG_H_
+
+
+#include <stdint.h>
+#include <sec_crypto_errcode.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ \brief Get data from the TRNG engine
+ \param[out] data Pointer to buffer with data get from TRNG
+ \param[in] num Number of data items,uinit in uint32
+ \return error code
+*/
+uint32_t sc_rng_get_multi_word(uint32_t *data, uint32_t num);
+
+/**
+ \brief Get data from the TRNG engine
+ \return error code
+*/
+uint32_t sc_rng_get_single_word(uint32_t *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRV_TRNG_H_ */
diff --git a/lib/sec_library/include/sec_crypto_rsa.h b/lib/sec_library/include/sec_crypto_rsa.h
new file mode 100755
index 00000000..03defbe4
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_rsa.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file seccrypt_rsa.h
+ * @brief Header File for RSA
+ * @version V1.0
+ * @date 20. Jul 2020
+ * @model rsa
+ ******************************************************************************/
+#ifndef _SC_RSA_H_
+#define _SC_RSA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIG_SYSTEM_SECURE
+#include "drv/rsa.h"
+#endif
+
+
+#ifdef CONFIG_SEC_CRYPTO_RSA_SW
+#include "crypto_rsa.h"
+#endif
+
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <drv/common.h>
+#include <sec_crypto_errcode.h>
+
+
+//TODO Del this file after updating to sc2.0
+
+/*----- RSA Control Codes: Mode Parameters: Key Bits -----*/
+typedef enum {
+ SC_RSA_KEY_BITS_192 = 0, ///< 192 Key bits
+ SC_RSA_KEY_BITS_256, ///< 256 Key bits
+ SC_RSA_KEY_BITS_512, ///< 512 Key bits
+ SC_RSA_KEY_BITS_1024, ///< 1024 Key bits
+ SC_RSA_KEY_BITS_2048, ///< 2048 Key bits
+ SC_RSA_KEY_BITS_3072, ///< 3072 Key bits
+ SC_RSA_KEY_BITS_4096 ///< 4096 Key bits
+} sc_rsa_key_bits_t;
+
+typedef enum {
+ SC_RSA_PADDING_MODE_NO = 0, ///< RSA NO Padding Mode
+ SC_RSA_PADDING_MODE_PKCS1, ///< RSA PKCS1 Padding Mode
+ SC_RSA_PADDING_MODE_PKCS1_OAEP, ///< RSA PKCS1 OAEP Padding Mode
+ SC_RSA_PADDING_MODE_SSLV23, ///< RSA SSLV23 Padding Mode
+ SC_RSA_PADDING_MODE_X931, ///< RSA X931 Padding Mode
+ SC_RSA_PADDING_MODE_PSS ///< RSA PSS Padding Mode
+} sc_rsa_padding_type_t;
+
+typedef enum {
+ SC_RSA_HASH_TYPE_MD5 = 0,
+ SC_RSA_HASH_TYPE_SHA1,
+ SC_RSA_HASH_TYPE_SHA224,
+ SC_RSA_HASH_TYPE_SHA256,
+ SC_RSA_HASH_TYPE_SHA384,
+ SC_RSA_HASH_TYPE_SHA512
+} sc_rsa_hash_type_t;
+
+typedef struct {
+// #if (defined(CONFIG_SYSTEM_SECURE) && defined(CONFIG_CSI_V2))
+// csi_rsa_context_t rsa_ctx;
+// #else
+ void * n; ///< Pointer to the public modulus
+ void * e; ///< Pointer to the public exponent
+ void * d; ///< Pointer to the private exponent
+ sc_rsa_key_bits_t key_bits; ///< RSA KEY BITS
+ sc_rsa_padding_type_t padding_type; ///< RSA PADDING TYPE
+ sc_rsa_hash_type_t hash_type;
+// #endif
+} sc_rsa_context_t;
+
+/**
+\brief RSA State
+*/
+typedef struct {
+ uint8_t busy : 1; ///< Calculate busy flag
+ uint8_t error : 1; ///< Calculate error flag
+} sc_rsa_state_t;
+
+typedef struct {
+#ifdef CONFIG_SYSTEM_SECURE
+#ifdef CONFIG_CSI_V1
+ rsa_handle_t handle;
+#endif /* CONFIG_CSI_V1 */
+#ifdef CONFIG_CSI_V2
+ csi_rsa_t csi_rsa;
+#endif
+#endif
+#if defined(CONFIG_SEC_CRYPTO_RSA_SW)
+ sc_mbedtls_rsa_context rsa_ctx;
+#endif
+ sc_rsa_key_bits_t bits;
+} sc_rsa_t;
+
+/****** RSA Event *****/
+typedef enum {
+ SC_RSA_EVENT_COMPLETE = 0, ///< rsa event completed
+ SC_RSA_EVENT_VERIFY_SUCCESS,
+ SC_RSA_EVENT_VERIFY_FAILED,
+ SC_RSA_EVENT_ERROR, ///< error event
+} sc_rsa_event_t;
+
+typedef void (*sc_rsa_callback_t)(
+ sc_rsa_t *rsa, sc_rsa_event_t event,
+ void *arg); ///< Pointer to \ref sc_rsa_callback_t : RSA Event call back.
+
+// Function documentation
+
+/**
+ \brief Initialize RSA Interface. 1. Initializes the resources needed for the RSA interface 2.registers event callback function
+ \param[in] rsa rsa handle to operate.
+ \param[in] idx device id
+ \param[in] data_bits rsa bit width
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_init(sc_rsa_t *rsa, uint32_t idx, sc_rsa_key_bits_t data_bits);
+
+/**
+ \brief De-initialize RSA Interface. stops operation and releases the software resources used by the interface
+ \param[in] rsa rsa handle to operate.
+ \return none
+*/
+void sc_rsa_uninit(sc_rsa_t *rsa);
+
+/**
+ \brief attach the callback handler to RSA
+ \param[in] rsa operate handle.
+ \param[in] cb callback function
+ \param[in] arg user can define it by himself as callback's param
+ \return error code
+*/
+uint32_t sc_rsa_attach_callback(sc_rsa_t *rsa, sc_rsa_callback_t cb, void *arg);
+
+/**
+ \brief detach the callback handler
+ \param[in] rsa operate handle.
+*/
+void sc_rsa_detach_callback(sc_rsa_t *rsa);
+
+/**
+ \brief generate rsa key pair.
+ \param[in] rsa rsa handle to operate.
+ \param[out] context Pointer to the rsa context
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_gen_key(sc_rsa_t *rsa, sc_rsa_context_t *context);
+
+/**
+ \brief encrypt
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] out Pointer to the result buffer
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_encrypt(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *out);
+
+/**
+ \brief decrypt
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] out Pointer to the result buffer
+ \param[out] out_size the result size
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_decrypt(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *out, uint32_t *out_size);
+
+/**
+ \brief rsa sign
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] signature Pointer to the signature
+ \param[in] hash_type the source data hash type
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_sign(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src, uint32_t src_size,
+ void *signature, sc_rsa_hash_type_t hash_type);
+
+/**
+ \brief rsa verify
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[in] signature Pointer to the signature
+ \param[in] sig_size the signature size
+ \param[in] hash_type the source data hash type
+ \return verify result
+*/
+bool sc_rsa_verify(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src, uint32_t src_size,
+ void *signature, uint32_t sig_size, sc_rsa_hash_type_t hash_type);
+
+/**
+ \brief encrypt(async mode)
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] out Pointer to the result buffer
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_encrypt_async(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *out);
+
+/**
+ \brief decrypt(async mode)
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] out Pointer to the result buffer
+ \param[out] out_size the result size
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_decrypt_async(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *out, uint32_t *out_size);
+
+/**
+ \brief rsa sign(async mode)
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[out] signature Pointer to the signature
+ \param[in] hash_type the source data hash type
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_sign_async(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *signature, sc_rsa_hash_type_t hash_type);
+
+/**
+ \brief rsa verify(async mode)
+ \param[in] rsa rsa handle to operate.
+ \param[in] context Pointer to the rsa context
+ \param[in] src Pointer to the source data.
+ \param[in] src_size the source data len
+ \param[in] signature Pointer to the signature
+ \param[in] sig_size the signature size
+ \param[in] hash_type the source data hash type
+ \return verify result
+*/
+uint32_t sc_rsa_verify_async(sc_rsa_t *rsa, sc_rsa_context_t *context, void *src,
+ uint32_t src_size, void *signature, uint32_t sig_size,
+ sc_rsa_hash_type_t hash_type);
+
+/**
+ \brief Get RSA state.
+ \param[in] rsa rsa handle to operate.
+ \param[out] state rsa state \ref sc_rsa_state_t.
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_get_state(sc_rsa_t *rsa, sc_rsa_state_t *state);
+
+/**
+ \brief Get big prime data
+ \param[in] rsa rsa handle to operate.
+ \param[in] p Pointer to the prime
+ \param[in] bit_length Pointer to the prime bit length
+ \return \ref uint32_t
+*/
+uint32_t sc_rsa_get_prime(sc_rsa_t *rsa, void *p, uint32_t bit_length);
+
+/**
+ \brief enable rsa power manage
+ \param[in] rsa rsa handle to operate.
+ \return error code
+*/
+uint32_t sc_rsa_enable_pm(sc_rsa_t *rsa);
+
+/**
+ \brief disable rsa power manage
+ \param[in] rsa rsa handle to operate.
+*/
+void sc_rsa_disable_pm(sc_rsa_t *rsa);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SC_RSA_H_ */
diff --git a/lib/sec_library/include/sec_crypto_sha.h b/lib/sec_library/include/sec_crypto_sha.h
new file mode 100755
index 00000000..aa31fde2
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_sha.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file seccrypt_sha.h
+ * @brief Header File for SHA
+ * @version V1.0
+ * @date 20. Jul 2020
+ * @model sha
+ ******************************************************************************/
+#ifndef _SC_SHA_H_
+#define _SC_SHA_H_
+
+#include <stdint.h>
+#ifdef CONFIG_SYSTEM_SECURE
+#include "drv/sha.h"
+#include "soc.h"
+#endif
+#ifdef CONFIG_SEC_CRYPTO_SM3
+#include "drv/sm3.h"
+#endif
+
+#include <sec_crypto_errcode.h>
+
+
+#ifdef CONFIG_SEC_CRYPTO_SHA_SW
+#include "crypto_sha1.h"
+#include "crypto_sha256.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----- SHA Control Codes: Mode -----*/
+typedef enum {
+ SC_SHA_MODE_1 = 1U, ///< SHA_1 mode
+ SC_SHA_MODE_256, ///< SHA_256 mode
+ SC_SHA_MODE_224, ///< SHA_224 mode
+ SC_SHA_MODE_512, ///< SHA_512 mode
+ SC_SHA_MODE_384, ///< SHA_384 mode
+ SC_SHA_MODE_512_256, ///< SHA_512_256 mode
+ SC_SHA_MODE_512_224, ///< SHA_512_224 mode
+ SC_SM3_MODE,
+} sc_sha_mode_t;
+
+/**
+\brief SHA State
+*/
+typedef struct {
+ uint32_t busy : 1; ///< calculate busy flag
+ uint32_t error : 1; ///< calculate error flag
+} sc_sha_state_t;
+
+typedef struct {
+#ifdef CONFIG_SYSTEM_SECURE
+#ifdef CONFIG_CSI_V1
+uint8_t ctx[SHA_CONTEXT_SIZE];
+#endif /* CONFIG_CSI_V1 */
+#ifdef CONFIG_CSI_V2
+ csi_sha_context_t ctx;
+ csi_sm3_context_t sm3ctx;
+#endif
+#endif
+#if defined(CONFIG_TEE_CA)
+ uint8_t ctx[224+8];
+#endif
+#if defined(CONFIG_SEC_CRYPTO_SHA_SW)
+ sc_mbedtls_sha1_context sha1_ctx;
+ sc_mbedtls_sha256_context sha2_ctx;
+#endif
+ sc_sha_mode_t mode; ///< sha mode
+} sc_sha_context_t;
+
+/****** SHA Event *****/
+typedef enum {
+ SC_SHA_EVENT_COMPLETE = 0U, ///< calculate completed
+ SC_SHA_EVENT_ERROR ///< calculate error
+} sc_sha_event_t;
+
+typedef struct sc_sha {
+#ifdef CONFIG_SYSTEM_SECURE
+#ifdef CONFIG_CSI_V1
+ sha_handle_t handle;
+ sc_sha_context_t ctx;
+ sc_sha_mode_t mode; ///< sha mode
+#endif /* CONFIG_CSI_V1 */
+#ifdef CONFIG_CSI_V2
+ csi_sha_t csi_sha;
+ csi_sm3_t csi_sm3;
+#endif
+#endif
+#if defined(CONFIG_TEE_CA)
+#endif
+} sc_sha_t;
+
+// Function documentation
+
+/**
+ \brief Initialize SHA Interface. Initializes the resources needed for the SHA interface
+ \param[in] sha operate handle.
+ \param[in] idx index of sha
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sha_init(sc_sha_t *sha, uint32_t idx);
+
+/**
+ \brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
+ \param[in] sha sha handle to operate.
+ \return none
+*/
+void sc_sha_uninit(sc_sha_t *sha);
+
+/**
+ \brief attach the callback handler to SHA
+ \param[in] sha operate handle.
+ \param[in] callback callback function
+ \param[in] arg callback's param
+ \return error code
+*/
+uint32_t sc_sha_attach_callback(sc_sha_t *sha, void *callback, void *arg);
+
+/**
+ \brief detach the callback handler
+ \param[in] sha operate handle.
+*/
+void sc_sha_detach_callback(sc_sha_t *sha);
+
+/**
+ \brief start the engine
+ \param[in] sha sha handle to operate.
+ \param[in] context Pointer to the sha context \ref sc_sha_context_t
+ \param[in] mode sha mode \ref sc_sha_mode_t
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sha_start(sc_sha_t *sha, sc_sha_context_t *context, sc_sha_mode_t mode);
+
+/**
+ \brief update the engine
+ \param[in] sha sha handle to operate.
+ \param[in] context Pointer to the sha context \ref sc_sha_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size the data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sha_update(sc_sha_t *sha, sc_sha_context_t *context, const void *input, uint32_t size);
+
+/**
+ \brief accumulate the engine (async mode)
+ \param[in] sha sha handle to operate.
+ \param[in] context Pointer to the sha context \ref sc_sha_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size the data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sha_update_async(sc_sha_t *sha, sc_sha_context_t *context, const void *input,
+ uint32_t size);
+
+/**
+ \brief finish the engine
+ \param[in] sha sha handle to operate.
+ \param[in] context Pointer to the sha context \ref sc_sha_context_t
+ \param[out] output Pointer to the result data
+ \param[out] out_size Pointer to the result data size(bytes)
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sha_finish(sc_sha_t *sha, sc_sha_context_t *context, void *output, uint32_t *out_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _sc_SHA_H_ */
diff --git a/lib/sec_library/include/sec_crypto_sm2.h b/lib/sec_library/include/sec_crypto_sm2.h
new file mode 100755
index 00000000..e9e83203
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_sm2.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file sec_crypt_sm2.h
+ * @brief Header File for SM2
+ * @version V1.0
+ * @date 20. Jul 2021
+ * @model sm2
+ ******************************************************************************/
+#ifndef _SC_SM2_H_
+#define _SC_SM2_H_
+
+#ifdef CONFIG_SEC_CRYPTO_SM2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "drv/sm2.h"
+
+typedef struct {
+ uint32_t sm2_curve : 1; ///< supports 256bits curve
+} sc_sm2_capabilities_t;
+
+/**
+\brief SM2 ciphertext order
+*/
+typedef enum {
+ SC_SM2_C1C3C2 = 0,
+ SC_SM2_C1C2C3,
+} sc_sm2_cipher_order_e;
+
+typedef enum {
+ SC_SM2_ENDIAN_LITTLE = 0, ///< Little Endian
+ SC_SM2_ENDIAN_BIG ///< Big Endian
+} sc_sm2_endian_mode_e;
+
+/**
+\brief SM2 status
+*/
+typedef struct {
+ uint32_t busy : 1; ///< Calculate busy flag
+} sc_sm2_state_t;
+
+/**
+\brief SM2 key exchange role
+*/
+typedef enum { SC_SM2_Role_Sponsor = 0, SC_SM2_Role_Responsor } sc_sm2_exchange_role_e;
+
+/****** SM2 Event *****/
+typedef enum {
+ SC_SM2_EVENT_MAKE_KEY_COMPLETE = 0, ///< Make key completed
+ SC_SM2_EVENT_ENCRYPT_COMPLETE, ///< Encrypt completed
+ SC_SM2_EVENT_DECRYPT_COMPLETE, ///< Decrypt completed
+ SC_SM2_EVENT_SIGN_COMPLETE, ///< Sign completed
+ SC_SM2_EVENT_VERIFY_COMPLETE, ///< Verify completed
+ SC_SM2_EVENT_EXCHANGE_KEY_COMPLETE, ///< Exchange key completed
+} sc_sm2_event_e;
+
+typedef struct {
+#ifdef CONFIG_CSI_V2
+ csi_sm2_t sm2;
+#endif
+} sc_sm2_t;
+
+///< Pointer to \ref sc_sm2_callback_t : SM2 Event call back.
+typedef void (*sc_sm2_callback_t)(sc_sm2_event_e event);
+
+/**
+ \brief Initialize SM2.
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] idx device id
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_init(sc_sm2_t *sm2, uint32_t idx);
+
+/**
+ \brief De-initialize SM2 Interface. stops operation and releases the
+ software resources used by the interface \param[in] sm2 sm2 handle to
+ operate. \return none
+*/
+void sc_sm2_uninit(sc_sm2_t *sm2);
+
+/**
+ \brief sm2 get capability.
+ \param[in] sm2 Operate handle.
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_config(sc_sm2_t *sm2, sc_sm2_cipher_order_e co,
+ sc_sm2_endian_mode_e endian);
+
+/**
+ \brief Attach the callback handler to SM2
+ \param[in] sm2 Operate handle.
+ \param[in] cb Callback function
+ \param[in] arg User can define it by himself as callback's param
+ \return Error code \ref uint32_t
+*/
+uint32_t sc_sm2_attach_callback(sc_sm2_t *sm2, sc_sm2_callback_t cb, void *arg);
+
+/**
+ \brief Detach the callback handler
+ \param[in] sm2 Operate handle.
+*/
+void sc_sm2_detach_callback(sc_sm2_t *sm2);
+
+/**
+ \brief sm2 get capability.
+ \param[in] sm2 Operate handle.
+ \param[out] cap Pointer of sc_sm2_capabilities_t.
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_get_capabilities(sc_sm2_t *sm2, sc_sm2_capabilities_t *cap);
+
+uint32_t sc_sm2_check_keypair(sc_sm2_t *sm2, uint8_t pubkey[65],
+ uint8_t prikey[32]);
+
+/**
+ \brief generate sm2 key.
+ \param[in] sm2 sm2 handle to operate.
+ \param[out] private Pointer to the sm2 private key, alloc by caller.
+ \param[out] public Pointer to the sm2 public key, alloc by caller.
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_gen_key(sc_sm2_t *sm2, uint8_t pubkey[65], uint8_t prikey[32]);
+
+/**
+ \brief sm2 sign
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_sign(sc_sm2_t *sm2, uint8_t d[32], uint8_t prikey[32],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 sign
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return \ref uint32_t
+*/
+uint32_t sc_sm2_sign_async(sc_sm2_t *sm2, uint8_t d[32], uint8_t prikey[32],
+ uint8_t s[64]);
+
+/* TODO */
+/**
+ \brief sm2 verify
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return verify result
+*/
+bool sc_sm2_verify(sc_sm2_t *sm2, uint8_t d[32], uint8_t pubkey[65],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 verify
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return verify result
+*/
+bool sc_sm2_verify_async(sc_sm2_t *sm2, uint8_t d[32], uint8_t pubkey[65],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 encrypto
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] plain Pointer to the plaintext.
+ \param[in] PlainByteLen plaintext len
+ \param[in] pubKey public key.
+ \param[out] cipher Pointer to the chipher
+ \param[out] cipher_byte_len Pointer to the chipher len.
+ \return uint32_t
+*/
+uint32_t sc_sm2_encrypt(sc_sm2_t *sm2, uint8_t *plain, uint32_t plain_len,
+ uint8_t pubKey[65], uint8_t *cipher,
+ uint32_t *cipher_len);
+
+/**
+ \brief sm2 encrypto
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] cipher Pointer to the chipher
+ \param[in] CipherByteLen chipher len.
+ \param[in] prikey private key.
+ \param[out] plain Pointer to the plaintext.
+ \param[out] PlainByteLen plaintext len
+ \return uint32_t
+*/
+uint32_t sc_sm2_decrypt(sc_sm2_t *sm2, uint8_t *cipher, uint32_t cipher_len,
+ uint8_t prikey[32], uint8_t *plain,
+ uint32_t *plain_len);
+
+/**
+ \brief sm2 key exchange
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+uint32_t sc_sm2_exchangekey(sc_sm2_t *sm2, sc_sm2_exchange_role_e role,
+ uint8_t *da, uint8_t *pb, uint8_t *ra1, uint8_t *ra,
+ uint8_t *rb, uint8_t *za, uint8_t *zb,
+ uint32_t k_len, uint8_t *ka, uint8_t *s1,
+ uint8_t *sa);
+
+/**
+ \brief sm2 key exchange get Z.
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+uint32_t sc_sm2_getZ(sc_sm2_t *sm2, uint8_t *id, uint32_t id_len,
+ uint8_t pubkey[65], uint8_t z[32]);
+
+/**
+ \brief sm2 key exchange get E
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+uint32_t sc_sm2_getE(sc_sm2_t *sm2, uint8_t *m, uint32_t len, uint8_t z[32],
+ uint8_t e[32]);
+
+/**
+ \brief Get SM2 state.
+ \param[in] sm2 SM2 handle to operate.
+ \param[out] state SM2 state \ref sc_sm2_state_t.
+ \return Error code \ref uint32_t
+*/
+uint32_t sc_sm2_get_state(sc_sm2_t *sm2, sc_sm2_state_t *state);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif
+
+#endif /* _SC_SM2_H_ */
diff --git a/lib/sec_library/include/sec_crypto_sm4.h b/lib/sec_library/include/sec_crypto_sm4.h
new file mode 100755
index 00000000..e8208145
--- /dev/null
+++ b/lib/sec_library/include/sec_crypto_sm4.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file sec_crypt_sm4.h
+ * @brief Header File for SM4
+ * @version V1.0
+ * @date 20. Jul 2021
+ * @model sm4
+ ******************************************************************************/
+
+#ifndef _SC_SM4_H_
+#define _SC_SM4_H_
+
+
+#ifdef CONFIG_CSI_V2
+#include "drv/sm4.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+\brief SM4 Ctrl Block
+*/
+typedef struct {
+#ifdef CONFIG_CSI_V2
+ csi_sm4_t sm4;
+#endif
+} sc_sm4_t;
+
+// Function documentation
+/**
+ \brief Initialize sm4 Interface. Initializes the resources needed for
+ the sm4 interface \param[in] sm4 operate handle \param[in] idx device
+ id \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_init(sc_sm4_t *sm4, uint32_t idx);
+
+/**
+ \brief De-initialize sm4 Interface. stops operation and releases the
+ software resources used by the interface \param[in] sm4 handle to operate
+ \return None
+*/
+void sc_sm4_uninit(sc_sm4_t *sm4);
+
+/**
+ \brief Set encrypt key
+ \param[in] sm4 handle to operate
+ \param[in] key Pointer to the key buf
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_set_encrypt_key(sc_sm4_t *sm4, uint8_t *key);
+
+/**
+ \brief Set decrypt key
+ \param[in] sm4 handle to operate
+ \param[in] key Pointer to the key buf
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_set_decrypt_key(sc_sm4_t *sm4, uint8_t *key);
+
+/**
+ \brief sm4 ecb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ecb_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size);
+
+/**
+ \brief sm4 ecb decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ecb_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size);
+
+/**
+ \brief sm4 cbc encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cbc_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cbc decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cbc_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb1 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb1_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb1 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb1_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb8 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb8_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb8 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb8_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb128 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb128_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 cfb128 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_cfb128_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+/**
+ \brief sm4 ofb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ofb_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 ofb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ofb_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 ctr encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter counter
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ctr_encrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t nonce_counter[16]);
+/**
+ \brief sm4 ctr encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter counter
+ \return error code \ref uint32_t
+*/
+uint32_t sc_sm4_ctr_decrypt(sc_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t nonce_counter[16]);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif /* _SC_SM4_H_ */
diff --git a/lib/sec_library/include/sec_library.h b/lib/sec_library/include/sec_library.h
new file mode 100755
index 00000000..1cb043ab
--- /dev/null
+++ b/lib/sec_library/include/sec_library.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+/******************************************************************************
+ * @file sec_library.h
+ * @brief Header File for sec library
+ * @version V1.0
+ * @date 20. Jul 2021
+ * @model sm4
+ ******************************************************************************/
+
+#ifndef _SL_H_
+#define _SL_H_
+
+#endif /* _SL_H_ */
diff --git a/lib/sec_library/include/sha.h b/lib/sec_library/include/sha.h
new file mode 100644
index 00000000..75472f12
--- /dev/null
+++ b/lib/sec_library/include/sha.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/sha.h
+ * @brief Header File for SHA Driver
+ * @version V1.0
+ * @date 9. Oct 2020
+ * @model sha
+ ******************************************************************************/
+
+#ifndef _DRV_SHA_H_
+#define _DRV_SHA_H_
+
+#include <drv/common.h>
+#include <drv/dma.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****** SHA mode ******/
+typedef enum {
+ SHA_MODE_1 = 1U, ///< SHA_1 mode
+ SHA_MODE_256, ///< SHA_256 mode
+ SHA_MODE_224, ///< SHA_224 mode
+ SHA_MODE_512, ///< SHA_512 mode
+ SHA_MODE_384, ///< SHA_384 mode
+ SHA_MODE_512_256, ///< SHA_512_256 mode
+ SHA_MODE_512_224 ///< SHA_512_224 mode
+} csi_sha_mode_t;
+
+/****** SHA State ******/
+typedef struct {
+ uint32_t busy : 1; ///< Calculate busy flag
+ uint32_t error : 1; ///< Calculate error flag
+} csi_sha_state_t;
+
+typedef struct {
+ csi_sha_mode_t mode; ///< SHA mode
+ uint32_t total[2]; ///< Number of bytes processed
+ uint32_t state[16]; ///< Intermediate digest state
+ uint8_t buffer[128]; ///< Data block being processed
+} csi_sha_context_t;
+
+/****** SHA Event ******/
+typedef enum {
+ SHA_EVENT_COMPLETE = 0U, ///< Calculate completed
+ SHA_EVENT_ERROR ///< Calculate error
+} csi_sha_event_t;
+
+typedef struct csi_sha csi_sha_t;
+
+struct csi_sha {
+ csi_dev_t dev; ///< SHA hw-device info
+ void (*callback)(csi_sha_t *sha, csi_sha_event_t event, void *arg); ///< SHA event callback for user
+ void *arg; ///< SHA custom designed param passed to evt_cb
+ csi_dma_ch_t *dma_in; ///< SHA in dma handle param
+ csi_sha_state_t state; ///< SHA state
+ void *priv;
+};
+
+/**
+ \brief Initialize SHA Interface. Initializes the resources needed for the SHA interface
+ \param[in] sha Operate handle
+ \param[in] idx Index of SHA
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_init(csi_sha_t *sha, uint32_t idx);
+
+/**
+ \brief De-initialize SHA Interface. Stops operation and releases the software resources used by the interface
+ \param[in] sha SHA handle to operate
+ \return None
+*/
+void csi_sha_uninit(csi_sha_t *sha);
+
+/**
+ \brief Attach the callback handler to SHA
+ \param[in] sha Handle to operate
+ \param[in] callback Callback function
+ \param[in] arg Callback's param
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_attach_callback(csi_sha_t *sha, void *callback, void *arg);
+
+/**
+ \brief Detach the callback handler
+ \param[in] sha Handle to operate
+ \return None
+*/
+void csi_sha_detach_callback(csi_sha_t *sha);
+
+/**
+ \brief Start the engine
+ \param[in] sha Handle to operate
+ \param[in] context Pointer to the SHA context \ref csi_sha_context_t
+ \param[in] mode SHA mode \ref csi_sha_mode_t
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_start(csi_sha_t *sha, csi_sha_context_t *context, csi_sha_mode_t mode);
+
+/**
+ \brief Update the engine
+ \param[in] sha Handle to operate
+ \param[in] context Pointer to the SHA context \ref csi_sha_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size The data size
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_update(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size);
+
+/**
+ \brief Accumulate the engine (async mode)
+ \param[in] sha Handle to operate
+ \param[in] context Pointer to the SHA context \ref csi_sha_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size The data size
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_update_async(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size);
+
+/**
+ \brief Finish the engine
+ \param[in] sha Handle to operate
+ \param[in] context Pointer to the SHA context \ref csi_sha_context_t
+ \param[out] output Pointer to the result data
+ \param[out] out_size Pointer to the result data size(bytes)
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_finish(csi_sha_t *sha, csi_sha_context_t *context, void *output, uint32_t *out_size);
+
+/**
+ \brief Get SHA state
+ \param[in] sha Handle to operate
+ \param[out] state SHA state \ref csi_sha_state_t
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_get_state(csi_sha_t *sha, csi_sha_state_t *state);
+
+/**
+ \brief Enable SHA power manage
+ \param[in] sha Handle to operate
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sha_enable_pm(csi_sha_t *sha);
+
+/**
+ \brief Disable SHA power manage
+ \param[in] sha Handle to operate
+ \return None
+*/
+void csi_sha_disable_pm(csi_sha_t *sha);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DRV_SHA_H_ */
diff --git a/lib/sec_library/include/sm2.h b/lib/sec_library/include/sm2.h
new file mode 100644
index 00000000..24b299db
--- /dev/null
+++ b/lib/sec_library/include/sm2.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/sm2.h
+ * @brief Header File for SM2 Driver
+ * @version V2.0
+ * @date 9. DEC 2020
+ * @model SM2
+ ******************************************************************************/
+
+#ifndef _DRV_SM2_H_
+#define _DRV_SM2_H_
+
+#include <stdint.h>
+#include <drv/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uint32_t sm2_curve : 1; ///< supports 256bits curve
+} sm2_capabilities_t;
+
+/**
+\brief SM2 ciphertext order
+*/
+typedef enum {
+ SM2_C1C3C2 = 0,
+ SM2_C1C2C3,
+} sm2_cipher_order_e;
+
+typedef enum {
+ SM2_ENDIAN_LITTLE = 0, ///< Little Endian
+ SM2_ENDIAN_BIG ///< Big Endian
+} sm2_endian_mode_e;
+
+/**
+\brief SM2 status
+*/
+typedef struct {
+ uint32_t busy : 1; ///< Calculate busy flag
+} csi_sm2_state_t;
+
+/**
+\brief SM2 key exchange role
+*/
+typedef enum { SM2_Role_Sponsor = 0, SM2_Role_Responsor } sm2_exchange_role_e;
+
+/****** SM2 Event *****/
+typedef enum {
+ SM2_EVENT_MAKE_KEY_COMPLETE = 0, ///< Make key completed
+ SM2_EVENT_ENCRYPT_COMPLETE, ///< Encrypt completed
+ SM2_EVENT_DECRYPT_COMPLETE, ///< Decrypt completed
+ SM2_EVENT_SIGN_COMPLETE, ///< Sign completed
+ SM2_EVENT_VERIFY_COMPLETE, ///< Verify completed
+ SM2_EVENT_EXCHANGE_KEY_COMPLETE, ///< Exchange key completed
+} sm2_event_e;
+
+typedef struct {
+ csi_dev_t dev;
+ void * cb;
+ void * arg;
+ csi_sm2_state_t state;
+ void * prim;
+} csi_sm2_t;
+
+///< Pointer to \ref csi_sm2_callback_t : SM2 Event call back.
+typedef void (*csi_sm2_callback_t)(sm2_event_e event);
+
+/**
+ \brief Initialize SM2.
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] idx device id
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_init(csi_sm2_t *sm2, uint32_t idx);
+
+/**
+ \brief De-initialize SM2 Interface. stops operation and releases the software resources used by the interface
+ \param[in] sm2 sm2 handle to operate.
+ \return none
+*/
+void csi_sm2_uninit(csi_sm2_t *sm2);
+
+/**
+ \brief sm2 get capability.
+ \param[in] sm2 Operate handle.
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_config(csi_sm2_t *sm2, sm2_cipher_order_e co,
+ sm2_endian_mode_e endian);
+
+/**
+ \brief Attach the callback handler to SM2
+ \param[in] sm2 Operate handle.
+ \param[in] cb Callback function
+ \param[in] arg User can define it by himself as callback's param
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm2_attach_callback(csi_sm2_t *sm2, csi_sm2_callback_t cb,
+ void *arg);
+
+/**
+ \brief Detach the callback handler
+ \param[in] sm2 Operate handle.
+*/
+void csi_sm2_detach_callback(csi_sm2_t *sm2);
+
+/**
+ \brief sm2 get capability.
+ \param[in] sm2 Operate handle.
+ \param[out] cap Pointer of sm2_capabilities_t.
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_get_capabilities(csi_sm2_t *sm2, sm2_capabilities_t *cap);
+
+csi_error_t csi_sm2_check_keypair(csi_sm2_t *sm2, uint8_t pubkey[65],
+ uint8_t prikey[32]);
+
+/**
+ \brief generate sm2 key.
+ \param[in] sm2 sm2 handle to operate.
+ \param[out] private Pointer to the sm2 private key, alloc by caller.
+ \param[out] public Pointer to the sm2 public key, alloc by caller.
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_gen_key(csi_sm2_t *sm2, uint8_t pubkey[65],
+ uint8_t prikey[32]);
+
+/**
+ \brief sm2 sign
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_sign(csi_sm2_t *sm2, uint8_t d[32], uint8_t prikey[32],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 sign
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return \ref uint32_t
+*/
+csi_error_t csi_sm2_sign_async(csi_sm2_t *sm2, uint8_t d[32],
+ uint8_t prikey[32], uint8_t s[64]);
+
+/* TODO */
+/**
+ \brief sm2 verify
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return verify result
+*/
+bool csi_sm2_verify(csi_sm2_t *sm2, uint8_t d[32], uint8_t pubkey[65],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 verify
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] d Pointer to the digest.
+ \param[out] privkey Pointer to the private key
+ \param[out] s Pointer to the signature
+ \return verify result
+*/
+bool csi_sm2_verify_async(csi_sm2_t *sm2, uint8_t d[32], uint8_t pubkey[65],
+ uint8_t s[64]);
+
+/**
+ \brief sm2 encrypto
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] Plain Pointer to the plaintext.
+ \param[in] PlainByteLen plaintext len
+ \param[in] pubKey public key.
+ \param[out] Cipher Pointer to the chipher
+ \param[out] CipherByteLen Pointer to the chipher len.
+ \return uint32_t
+*/
+csi_error_t csi_sm2_encrypt(csi_sm2_t *sm2, uint8_t *Plain,
+ uint32_t PlainByteLen, uint8_t pubKey[65],
+ uint8_t *Cipher, uint32_t *CipherByteLen);
+
+/**
+ \brief sm2 encrypto
+ \param[in] sm2 sm2 handle to operate.
+ \param[in] Cipher Pointer to the chipher
+ \param[in] CipherByteLen chipher len.
+ \param[in] prikey private key.
+ \param[out] Plain Pointer to the plaintext.
+ \param[out] PlainByteLen plaintext len
+ \return uint32_t
+*/
+csi_error_t csi_sm2_decrypt(csi_sm2_t *sm2, uint8_t *Cipher,
+ uint32_t CipherByteLen, uint8_t prikey[32],
+ uint8_t *Plain, uint32_t *PlainByteLen);
+
+/**
+ \brief sm2 key exchange
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+csi_error_t csi_sm2_exchangekey(csi_sm2_t *sm2, sm2_exchange_role_e role,
+ uint8_t *dA, uint8_t *PB, uint8_t *rA,
+ uint8_t *RA, uint8_t *RB, uint8_t *ZA,
+ uint8_t *ZB, uint32_t kByteLen, uint8_t *KA,
+ uint8_t *S1, uint8_t *SA);
+
+/**
+ \brief sm2 key exchange get Z.
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+csi_error_t csi_sm2_getZ(csi_sm2_t *sm2, uint8_t *ID, uint32_t byteLenofID,
+ uint8_t pubKey[65], uint8_t Z[32]);
+
+/**
+ \brief sm2 key exchange get E
+ \param[in] sm2 sm2 handle to operate.
+ \return uint32_t
+*/
+csi_error_t csi_sm2_getE(csi_sm2_t *sm2, uint8_t *M, uint32_t byteLen,
+ uint8_t Z[32], uint8_t E[32]);
+
+/**
+ \brief Get SM2 state.
+ \param[in] sm2 SM2 handle to operate.
+ \param[out] state SM2 state \ref csi_sm2_state_t.
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm2_get_state(csi_sm2_t *sm2, csi_sm2_state_t *state);
+
+/**
+ \brief Enable sm2 power manage
+ \param[in] sm2 SM2 handle to operate.
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm2_enable_pm(csi_sm2_t *sm2);
+
+/**
+ \brief Disable sm2 power manage
+ \param[in] sm2 SM2 handle to operate.
+*/
+void csi_sm2_disable_pm(csi_sm2_t *sm2);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif
diff --git a/lib/sec_library/include/sm3.h b/lib/sec_library/include/sm3.h
new file mode 100644
index 00000000..9d5fc2c3
--- /dev/null
+++ b/lib/sec_library/include/sm3.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/sm3.h
+ * @brief Header File for SM3 Driver
+ * @version V2.0
+ * @date 9. DEC 2020
+ * @model SM3
+ ******************************************************************************/
+
+#ifndef _DRV_SM3_H_
+#define _DRV_SM3_H_
+
+#include <stdint.h>
+#include <drv/common.h>
+#include <drv/dma.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uint32_t total[2]; ///< Number of bytes processed
+ uint32_t state[16]; ///< Intermediate digest state
+ uint8_t buffer[64]; ///< Data block beingprocessed
+} csi_sm3_context_t;
+
+/****** SM3 State ******/
+typedef struct {
+ uint32_t busy : 1; ///< Calculate busy flag
+ uint32_t error : 1; ///< Calculate error flag
+} csi_sm3_state_t;
+
+
+/****** SM3 Event ******/
+typedef enum {
+ SM3_EVENT_COMPLETE = 0U, ///< Calculate completed
+ SM3_EVENT_ERROR ///< Calculate error
+} csi_sm3_event_t;
+
+typedef struct csi_sm3_t csi_sm3_t;
+
+struct csi_sm3_t {
+ csi_dev_t dev; ///< SM3 hw-device info
+ void (*callback)(csi_sm3_t *sm3, csi_sm3_event_t event,
+ void *arg); ///< SM3 event callback for user
+ void * arg; ///< SM3 custom designed param passed to evt_cb
+ csi_dma_ch_t * dma_in; ///< SM3 in dma handle param
+ csi_sm3_state_t state; ///< SM3 state
+ void * priv;
+};
+
+// Function documentation
+
+/**
+ \brief Initialize SM3 Interface. Initializes the resources needed for the SM3 interface
+ \param[in] sm3 operate handle.
+ \param[in] idx index of sm3
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm3_init(csi_sm3_t *sm3, uint32_t idx);
+
+/**
+ \brief De-initialize SM3 Interface. stops operation and releases the software resources used by the interface
+ \param[in] sm3 sm3 handle to operate.
+ \return none
+*/
+void csi_sm3_uninit(csi_sm3_t *sm3);
+
+/**
+ \brief Attach the callback handler to SM3
+ \param[in] sm3 Handle to operate
+ \param[in] callback Callback function
+ \param[in] arg Callback's param
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm3_attach_callback(csi_sm3_t *sm3, void *callback, void *arg);
+
+/**
+ \brief Detach the callback handler
+ \param[in] sm3 Handle to operate
+ \return None
+*/
+void csi_sm3_detach_callback(csi_sm3_t *sm3);
+
+/**
+ \brief start the engine
+ \param[in] sm3 sm3 handle to .operate
+ \param[in] context Pointer to the sm3 context \ref csi_sm3_context_t
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm3_start(csi_sm3_t *sm3, csi_sm3_context_t *context);
+
+/**
+ \brief update the engine
+ \param[in] sm3 sm3 handle to operate.
+ \param[in] context Pointer to the sm3 context \ref csi_sm3_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size the data size
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm3_update(csi_sm3_t *sm3, csi_sm3_context_t *context,
+ const uint8_t *input, uint32_t size);
+
+/**
+ \brief Accumulate the engine (async mode)
+ \param[in] sm3 Handle to operate
+ \param[in] context Pointer to the SM3 context \ref csi_sm3_context_t
+ \param[in] input Pointer to the Source data
+ \param[in] size The data size
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm3_update_async(csi_sm3_t *sm3, csi_sm3_context_t *context,
+ const uint8_t *input, uint32_t size);
+
+/**
+ \brief finish the engine
+ \param[in] sm3 sm3 handle to operate.
+ \param[in] context Pointer to the sm3 context \ref csi_sm3_context_t
+ \param[out] output Pointer to the result data
+ \param[out] out_size Pointer to the result data size(bytes)
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm3_finish(csi_sm3_t *sm3, csi_sm3_context_t *context,
+ uint8_t *output, uint32_t *out_size);
+
+/**
+ \brief Get SM3 state
+ \param[in] sm3 Handle to operate
+ \param[out] state SM3 state \ref csi_sm3_state_t
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm3_get_state(csi_sm3_t *sm3, csi_sm3_state_t *state);
+
+/**
+ \brief Enable SM3 power manage
+ \param[in] sm3 Handle to operate
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm3_enable_pm(csi_sm3_t *sm3);
+
+/**
+ \brief Disable SM3 power manage
+ \param[in] sm3 Handle to operate
+ \return None
+*/
+void csi_sm3_disable_pm(csi_sm3_t *sm3);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif //_DRV_SM3_H
diff --git a/lib/sec_library/include/sm4.h b/lib/sec_library/include/sm4.h
new file mode 100644
index 00000000..3e4f59f1
--- /dev/null
+++ b/lib/sec_library/include/sm4.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017-2021 Alibaba Group Holding Limited
+ */
+
+/******************************************************************************
+ * @file drv/sm4.h
+ * @brief Header File for SM4 Driver
+ * @version V2.0
+ * @date 9. DEC 2020
+ * @model SM4
+ ******************************************************************************/
+
+#ifndef _DRV_SM4_H_
+#define _DRV_SM4_H_
+
+#include <stdint.h>
+#include <drv/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+\brief SM4 Ctrl Block
+*/
+typedef struct {
+ csi_dev_t dev;
+ void * priv;
+} csi_sm4_t;
+
+// Function documentation
+/**
+ \brief Initialize sm4 Interface. Initializes the resources needed for the sm4 interface
+ \param[in] sm4 operate handle
+ \param[in] idx device id
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_init(csi_sm4_t *sm4, uint32_t idx);
+
+/**
+ \brief De-initialize sm4 Interface. stops operation and releases the software resources used by the interface
+ \param[in] sm4 handle to operate
+ \return None
+*/
+void csi_sm4_uninit(csi_sm4_t *sm4);
+
+/**
+ \brief Set encrypt key
+ \param[in] sm4 handle to operate
+ \param[in] key Pointer to the key buf
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_set_encrypt_key(csi_sm4_t *sm4, uint8_t *key);
+
+/**
+ \brief Set decrypt key
+ \param[in] sm4 handle to operate
+ \param[in] key Pointer to the key buf
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_set_decrypt_key(csi_sm4_t *sm4, uint8_t *key);
+
+/**
+ \brief sm4 ecb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ecb_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size);
+
+/**
+ \brief sm4 ecb decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ecb_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size);
+
+/**
+ \brief sm4 cbc encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cbc_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cbc decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cbc_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb1 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb1_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb1 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb1_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb8 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb8_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb8 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb8_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv);
+
+/**
+ \brief sm4 cfb128 decrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb128_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 cfb128 encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_cfb128_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+/**
+ \brief sm4 ofb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ofb_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 ofb encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] iv init vector
+ \param[out] num the number of the 128-bit block we have used
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ofb_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t *iv, uint32_t *num);
+
+/**
+ \brief sm4 ctr encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter counter
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ctr_encrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t nonce_counter[16]);
+/**
+ \brief sm4 ctr encrypt
+ \param[in] sm4 handle to operate
+ \param[in] in Pointer to the Source data
+ \param[out] out Pointer to the Result data
+ \param[in] size the Source data size
+ \param[in] nonce_counter counter
+ \return error code \ref uint32_t
+*/
+csi_error_t csi_sm4_ctr_decrypt(csi_sm4_t *sm4, uint8_t *in, uint8_t *out,
+ uint32_t size, uint8_t nonce_counter[16]);
+
+/**
+ \brief Enable SM4 power manage
+ \param[in] sm4 Handle to operate
+ \return Error code \ref csi_error_t
+*/
+csi_error_t csi_sm4_enable_pm(csi_sm4_t *sm4);
+
+/**
+ \brief Disable SM4 power manage
+ \param[in] sm4 Handle to operate
+ \return None
+*/
+void csi_sm4_disable_pm(csi_sm4_t *sm4);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif // _DRV_SM4_H_
diff --git a/lib/sec_library/libsec_library.a b/lib/sec_library/libsec_library.a
new file mode 100644
index 00000000..fecfbb91
--- /dev/null
+++ b/lib/sec_library/libsec_library.a
Binary files differ
diff --git a/lib/sha1.c b/lib/sha1.c
new file mode 100644
index 00000000..8154e1e1
--- /dev/null
+++ b/lib/sha1.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ * based on:
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2003-2006 Christophe Devine
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif /* USE_HOSTCC */
+#include <watchdog.h>
+#include <u-boot/sha1.h>
+
+const uint8_t sha1_der_prefix[SHA1_DER_LEN] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
+ 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
+};
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) { \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts (sha1_context * ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+static void sha1_process(sha1_context *ctx, const unsigned char data[64])
+{
+ unsigned long temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE (W[0], data, 0);
+ GET_UINT32_BE (W[1], data, 4);
+ GET_UINT32_BE (W[2], data, 8);
+ GET_UINT32_BE (W[3], data, 12);
+ GET_UINT32_BE (W[4], data, 16);
+ GET_UINT32_BE (W[5], data, 20);
+ GET_UINT32_BE (W[6], data, 24);
+ GET_UINT32_BE (W[7], data, 28);
+ GET_UINT32_BE (W[8], data, 32);
+ GET_UINT32_BE (W[9], data, 36);
+ GET_UINT32_BE (W[10], data, 40);
+ GET_UINT32_BE (W[11], data, 44);
+ GET_UINT32_BE (W[12], data, 48);
+ GET_UINT32_BE (W[13], data, 52);
+ GET_UINT32_BE (W[14], data, 56);
+ GET_UINT32_BE (W[15], data, 60);
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) ( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) { \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P (A, B, C, D, E, W[0]);
+ P (E, A, B, C, D, W[1]);
+ P (D, E, A, B, C, W[2]);
+ P (C, D, E, A, B, W[3]);
+ P (B, C, D, E, A, W[4]);
+ P (A, B, C, D, E, W[5]);
+ P (E, A, B, C, D, W[6]);
+ P (D, E, A, B, C, W[7]);
+ P (C, D, E, A, B, W[8]);
+ P (B, C, D, E, A, W[9]);
+ P (A, B, C, D, E, W[10]);
+ P (E, A, B, C, D, W[11]);
+ P (D, E, A, B, C, W[12]);
+ P (C, D, E, A, B, W[13]);
+ P (B, C, D, E, A, W[14]);
+ P (A, B, C, D, E, W[15]);
+ P (E, A, B, C, D, R (16));
+ P (D, E, A, B, C, R (17));
+ P (C, D, E, A, B, R (18));
+ P (B, C, D, E, A, R (19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P (A, B, C, D, E, R (20));
+ P (E, A, B, C, D, R (21));
+ P (D, E, A, B, C, R (22));
+ P (C, D, E, A, B, R (23));
+ P (B, C, D, E, A, R (24));
+ P (A, B, C, D, E, R (25));
+ P (E, A, B, C, D, R (26));
+ P (D, E, A, B, C, R (27));
+ P (C, D, E, A, B, R (28));
+ P (B, C, D, E, A, R (29));
+ P (A, B, C, D, E, R (30));
+ P (E, A, B, C, D, R (31));
+ P (D, E, A, B, C, R (32));
+ P (C, D, E, A, B, R (33));
+ P (B, C, D, E, A, R (34));
+ P (A, B, C, D, E, R (35));
+ P (E, A, B, C, D, R (36));
+ P (D, E, A, B, C, R (37));
+ P (C, D, E, A, B, R (38));
+ P (B, C, D, E, A, R (39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P (A, B, C, D, E, R (40));
+ P (E, A, B, C, D, R (41));
+ P (D, E, A, B, C, R (42));
+ P (C, D, E, A, B, R (43));
+ P (B, C, D, E, A, R (44));
+ P (A, B, C, D, E, R (45));
+ P (E, A, B, C, D, R (46));
+ P (D, E, A, B, C, R (47));
+ P (C, D, E, A, B, R (48));
+ P (B, C, D, E, A, R (49));
+ P (A, B, C, D, E, R (50));
+ P (E, A, B, C, D, R (51));
+ P (D, E, A, B, C, R (52));
+ P (C, D, E, A, B, R (53));
+ P (B, C, D, E, A, R (54));
+ P (A, B, C, D, E, R (55));
+ P (E, A, B, C, D, R (56));
+ P (D, E, A, B, C, R (57));
+ P (C, D, E, A, B, R (58));
+ P (B, C, D, E, A, R (59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P (A, B, C, D, E, R (60));
+ P (E, A, B, C, D, R (61));
+ P (D, E, A, B, C, R (62));
+ P (C, D, E, A, B, R (63));
+ P (B, C, D, E, A, R (64));
+ P (A, B, C, D, E, R (65));
+ P (E, A, B, C, D, R (66));
+ P (D, E, A, B, C, R (67));
+ P (C, D, E, A, B, R (68));
+ P (B, C, D, E, A, R (69));
+ P (A, B, C, D, E, R (70));
+ P (E, A, B, C, D, R (71));
+ P (D, E, A, B, C, R (72));
+ P (C, D, E, A, B, R (73));
+ P (B, C, D, E, A, R (74));
+ P (A, B, C, D, E, R (75));
+ P (E, A, B, C, D, R (76));
+ P (D, E, A, B, C, R (77));
+ P (C, D, E, A, B, R (78));
+ P (B, C, D, E, A, R (79));
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update(sha1_context *ctx, const unsigned char *input,
+ unsigned int ilen)
+{
+ int fill;
+ unsigned long left;
+
+ if (ilen <= 0)
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < (unsigned long) ilen)
+ ctx->total[1]++;
+
+ if (left && ilen >= fill) {
+ memcpy ((void *) (ctx->buffer + left), (void *) input, fill);
+ sha1_process (ctx, ctx->buffer);
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while (ilen >= 64) {
+ sha1_process (ctx, input);
+ input += 64;
+ ilen -= 64;
+ }
+
+ if (ilen > 0) {
+ memcpy ((void *) (ctx->buffer + left), (void *) input, ilen);
+ }
+}
+
+static const unsigned char sha1_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish (sha1_context * ctx, unsigned char output[20])
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = (ctx->total[0] >> 29)
+ | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32_BE (high, msglen, 0);
+ PUT_UINT32_BE (low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ sha1_update (ctx, (unsigned char *) sha1_padding, padn);
+ sha1_update (ctx, msglen, 8);
+
+ PUT_UINT32_BE (ctx->state[0], output, 0);
+ PUT_UINT32_BE (ctx->state[1], output, 4);
+ PUT_UINT32_BE (ctx->state[2], output, 8);
+ PUT_UINT32_BE (ctx->state[3], output, 12);
+ PUT_UINT32_BE (ctx->state[4], output, 16);
+}
+
+/*
+ * Output = SHA-1( input buffer )
+ */
+void sha1_csum(const unsigned char *input, unsigned int ilen,
+ unsigned char *output)
+{
+ sha1_context ctx;
+
+ sha1_starts (&ctx);
+ sha1_update (&ctx, input, ilen);
+ sha1_finish (&ctx, output);
+}
+
+/*
+ * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
+ * bytes of input processed.
+ */
+void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
+ unsigned char *output, unsigned int chunk_sz)
+{
+ sha1_context ctx;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ const unsigned char *end, *curr;
+ int chunk;
+#endif
+
+ sha1_starts (&ctx);
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ curr = input;
+ end = input + ilen;
+ while (curr < end) {
+ chunk = end - curr;
+ if (chunk > chunk_sz)
+ chunk = chunk_sz;
+ sha1_update (&ctx, curr, chunk);
+ curr += chunk;
+ WATCHDOG_RESET ();
+ }
+#else
+ sha1_update (&ctx, input, ilen);
+#endif
+
+ sha1_finish (&ctx, output);
+}
+
+/*
+ * Output = HMAC-SHA-1( input buffer, hmac key )
+ */
+void sha1_hmac(const unsigned char *key, int keylen,
+ const unsigned char *input, unsigned int ilen,
+ unsigned char *output)
+{
+ int i;
+ sha1_context ctx;
+ unsigned char k_ipad[64];
+ unsigned char k_opad[64];
+ unsigned char tmpbuf[20];
+
+ memset (k_ipad, 0x36, 64);
+ memset (k_opad, 0x5C, 64);
+
+ for (i = 0; i < keylen; i++) {
+ if (i >= 64)
+ break;
+
+ k_ipad[i] ^= key[i];
+ k_opad[i] ^= key[i];
+ }
+
+ sha1_starts (&ctx);
+ sha1_update (&ctx, k_ipad, 64);
+ sha1_update (&ctx, input, ilen);
+ sha1_finish (&ctx, tmpbuf);
+
+ sha1_starts (&ctx);
+ sha1_update (&ctx, k_opad, 64);
+ sha1_update (&ctx, tmpbuf, 20);
+ sha1_finish (&ctx, output);
+
+ memset (k_ipad, 0, 64);
+ memset (k_opad, 0, 64);
+ memset (tmpbuf, 0, 20);
+ memset (&ctx, 0, sizeof (sha1_context));
+}
+
+#ifdef SELF_TEST
+/*
+ * FIPS-180-1 test vectors
+ */
+static const char sha1_test_str[3][57] = {
+ {"abc"},
+ {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
+ {""}
+};
+
+static const unsigned char sha1_test_sum[3][20] = {
+ {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
+ {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
+ {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test (void)
+{
+ int i, j;
+ unsigned char buf[1000];
+ unsigned char sha1sum[20];
+ sha1_context ctx;
+
+ for (i = 0; i < 3; i++) {
+ printf (" SHA-1 test #%d: ", i + 1);
+
+ sha1_starts (&ctx);
+
+ if (i < 2)
+ sha1_update (&ctx, (unsigned char *) sha1_test_str[i],
+ strlen (sha1_test_str[i]));
+ else {
+ memset (buf, 'a', 1000);
+ for (j = 0; j < 1000; j++)
+ sha1_update (&ctx, buf, 1000);
+ }
+
+ sha1_finish (&ctx, sha1sum);
+
+ if (memcmp (sha1sum, sha1_test_sum[i], 20) != 0) {
+ printf ("failed\n");
+ return (1);
+ }
+
+ printf ("passed\n");
+ }
+
+ printf ("\n");
+ return (0);
+}
+#else
+int sha1_self_test (void)
+{
+ return (0);
+}
+#endif
diff --git a/lib/sha256.c b/lib/sha256.c
new file mode 100644
index 00000000..c1fe93de
--- /dev/null
+++ b/lib/sha256.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2001-2003 Christophe Devine
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif /* USE_HOSTCC */
+#include <watchdog.h>
+#include <u-boot/sha256.h>
+
+const uint8_t sha256_der_prefix[SHA256_DER_LEN] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+ 0x00, 0x04, 0x20
+};
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) { \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+void sha256_starts(sha256_context * ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 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;
+}
+
+static void sha256_process(sha256_context *ctx, const uint8_t data[64])
+{
+ uint32_t temp1, temp2;
+ uint32_t W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32_BE(W[0], data, 0);
+ GET_UINT32_BE(W[1], data, 4);
+ GET_UINT32_BE(W[2], data, 8);
+ GET_UINT32_BE(W[3], data, 12);
+ GET_UINT32_BE(W[4], data, 16);
+ GET_UINT32_BE(W[5], data, 20);
+ GET_UINT32_BE(W[6], data, 24);
+ GET_UINT32_BE(W[7], data, 28);
+ GET_UINT32_BE(W[8], data, 32);
+ GET_UINT32_BE(W[9], data, 36);
+ GET_UINT32_BE(W[10], data, 40);
+ GET_UINT32_BE(W[11], data, 44);
+ GET_UINT32_BE(W[12], data, 48);
+ GET_UINT32_BE(W[13], data, 52);
+ GET_UINT32_BE(W[14], data, 56);
+ GET_UINT32_BE(W[15], data, 60);
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) { \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ 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];
+
+ P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
+ P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
+ P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
+ P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
+ P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
+ P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
+ P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
+ P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
+ P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
+ P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
+ P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+ P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+ P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+ P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+ P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+ P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+ P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+ P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+ P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+ P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+ P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+ P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+ P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+ P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+ P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+ P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
+ P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+ P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+ P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+ P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+ P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+ P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+ P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+ P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+ P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+ P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+ P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+ P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+ P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+ P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+ P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+ P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+ P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+ P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+ P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+ P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+ P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+ P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+ P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+ P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+ P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+ P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+ P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+ P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+ P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+ P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+ P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+ P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+ 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;
+}
+
+void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
+{
+ uint32_t left, fill;
+
+ if (!length)
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < length)
+ ctx->total[1]++;
+
+ if (left && length >= fill) {
+ memcpy((void *) (ctx->buffer + left), (void *) input, fill);
+ sha256_process(ctx, ctx->buffer);
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while (length >= 64) {
+ sha256_process(ctx, input);
+ length -= 64;
+ input += 64;
+ }
+
+ if (length)
+ memcpy((void *) (ctx->buffer + left), (void *) input, length);
+}
+
+static uint8_t sha256_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void sha256_finish(sha256_context * ctx, uint8_t digest[32])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ uint8_t msglen[8];
+
+ high = ((ctx->total[0] >> 29)
+ | (ctx->total[1] << 3));
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32_BE(high, msglen, 0);
+ PUT_UINT32_BE(low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ sha256_update(ctx, sha256_padding, padn);
+ sha256_update(ctx, msglen, 8);
+
+ PUT_UINT32_BE(ctx->state[0], digest, 0);
+ PUT_UINT32_BE(ctx->state[1], digest, 4);
+ PUT_UINT32_BE(ctx->state[2], digest, 8);
+ PUT_UINT32_BE(ctx->state[3], digest, 12);
+ PUT_UINT32_BE(ctx->state[4], digest, 16);
+ PUT_UINT32_BE(ctx->state[5], digest, 20);
+ PUT_UINT32_BE(ctx->state[6], digest, 24);
+ PUT_UINT32_BE(ctx->state[7], digest, 28);
+}
+
+/*
+ * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
+ * bytes of input processed.
+ */
+void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
+ unsigned char *output, unsigned int chunk_sz)
+{
+ sha256_context ctx;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ const unsigned char *end;
+ unsigned char *curr;
+ int chunk;
+#endif
+
+ sha256_starts(&ctx);
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ curr = (unsigned char *)input;
+ end = input + ilen;
+ while (curr < end) {
+ chunk = end - curr;
+ if (chunk > chunk_sz)
+ chunk = chunk_sz;
+ sha256_update(&ctx, curr, chunk);
+ curr += chunk;
+ WATCHDOG_RESET();
+ }
+#else
+ sha256_update(&ctx, input, ilen);
+#endif
+
+ sha256_finish(&ctx, output);
+}
diff --git a/lib/slre.c b/lib/slre.c
new file mode 100644
index 00000000..969c46a8
--- /dev/null
+++ b/lib/slre.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ * All rights reserved
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+
+/*
+ * Downloaded Sat Nov 5 17:43:06 CET 2011 at
+ * http://slre.sourceforge.net/1.0/slre.c
+ */
+
+#ifdef SLRE_TEST
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <common.h>
+#include <linux/ctype.h>
+#endif /* SLRE_TEST */
+
+#include <errno.h>
+
+#include <slre.h>
+
+enum {END, BRANCH, ANY, EXACT, ANYOF, ANYBUT, OPEN, CLOSE, BOL, EOL,
+ STAR, PLUS, STARQ, PLUSQ, QUEST, SPACE, NONSPACE, DIGIT};
+
+#ifdef SLRE_TEST
+static struct {
+ const char *name;
+ int narg;
+ const char *flags;
+} opcodes[] = {
+ {"END", 0, ""}, /* End of code block or program */
+ {"BRANCH", 2, "oo"}, /* Alternative operator, "|" */
+ {"ANY", 0, ""}, /* Match any character, "." */
+ {"EXACT", 2, "d"}, /* Match exact string */
+ {"ANYOF", 2, "D"}, /* Match any from set, "[]" */
+ {"ANYBUT", 2, "D"}, /* Match any but from set, "[^]"*/
+ {"OPEN ", 1, "i"}, /* Capture start, "(" */
+ {"CLOSE", 1, "i"}, /* Capture end, ")" */
+ {"BOL", 0, ""}, /* Beginning of string, "^" */
+ {"EOL", 0, ""}, /* End of string, "$" */
+ {"STAR", 1, "o"}, /* Match zero or more times "*" */
+ {"PLUS", 1, "o"}, /* Match one or more times, "+" */
+ {"STARQ", 1, "o"}, /* Non-greedy STAR, "*?" */
+ {"PLUSQ", 1, "o"}, /* Non-greedy PLUS, "+?" */
+ {"QUEST", 1, "o"}, /* Match zero or one time, "?" */
+ {"SPACE", 0, ""}, /* Match whitespace, "\s" */
+ {"NONSPACE", 0, ""}, /* Match non-space, "\S" */
+ {"DIGIT", 0, ""} /* Match digit, "\d" */
+};
+#endif /* SLRE_TEST */
+
+/*
+ * Commands and operands are all unsigned char (1 byte long). All code offsets
+ * are relative to current address, and positive (always point forward). Data
+ * offsets are absolute. Commands with operands:
+ *
+ * BRANCH offset1 offset2
+ * Try to match the code block that follows the BRANCH instruction
+ * (code block ends with END). If no match, try to match code block that
+ * starts at offset1. If either of these match, jump to offset2.
+ *
+ * EXACT data_offset data_length
+ * Try to match exact string. String is recorded in data section from
+ * data_offset, and has length data_length.
+ *
+ * OPEN capture_number
+ * CLOSE capture_number
+ * If the user have passed 'struct cap' array for captures, OPEN
+ * records the beginning of the matched substring (cap->ptr), CLOSE
+ * sets the length (cap->len) for respective capture_number.
+ *
+ * STAR code_offset
+ * PLUS code_offset
+ * QUEST code_offset
+ * *, +, ?, respectively. Try to gobble as much as possible from the
+ * matched buffer, until code block that follows these instructions
+ * matches. When the longest possible string is matched,
+ * jump to code_offset
+ *
+ * STARQ, PLUSQ are non-greedy versions of STAR and PLUS.
+ */
+
+static const char *meta_chars = "|.^$*+?()[\\";
+
+#ifdef SLRE_TEST
+
+static void
+print_character_set(FILE *fp, const unsigned char *p, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i > 0)
+ (void) fputc(',', fp);
+ if (p[i] == 0) {
+ i++;
+ if (p[i] == 0)
+ (void) fprintf(fp, "\\x%02x", p[i]);
+ else
+ (void) fprintf(fp, "%s", opcodes[p[i]].name);
+ } else if (isprint(p[i])) {
+ (void) fputc(p[i], fp);
+ } else {
+ (void) fprintf(fp, "\\x%02x", p[i]);
+ }
+ }
+}
+
+void
+slre_dump(const struct slre *r, FILE *fp)
+{
+ int i, j, ch, op, pc;
+
+ for (pc = 0; pc < r->code_size; pc++) {
+
+ op = r->code[pc];
+ (void) fprintf(fp, "%3d %s ", pc, opcodes[op].name);
+
+ for (i = 0; opcodes[op].flags[i] != '\0'; i++)
+ switch (opcodes[op].flags[i]) {
+ case 'i':
+ (void) fprintf(fp, "%d ", r->code[pc + 1]);
+ pc++;
+ break;
+ case 'o':
+ (void) fprintf(fp, "%d ",
+ pc + r->code[pc + 1] - i);
+ pc++;
+ break;
+ case 'D':
+ print_character_set(fp, r->data +
+ r->code[pc + 1], r->code[pc + 2]);
+ pc += 2;
+ break;
+ case 'd':
+ (void) fputc('"', fp);
+ for (j = 0; j < r->code[pc + 2]; j++) {
+ ch = r->data[r->code[pc + 1] + j];
+ if (isprint(ch)) {
+ (void) fputc(ch, fp);
+ } else {
+ (void) fprintf(fp,
+ "\\x%02x", ch);
+ }
+ }
+ (void) fputc('"', fp);
+ pc += 2;
+ break;
+ }
+
+ (void) fputc('\n', fp);
+ }
+}
+#endif /* SLRE_TEST */
+
+static void
+set_jump_offset(struct slre *r, int pc, int offset)
+{
+ assert(offset < r->code_size);
+
+ if (r->code_size - offset > 0xff)
+ r->err_str = "Jump offset is too big";
+ else
+ r->code[pc] = (unsigned char) (r->code_size - offset);
+}
+
+static void
+emit(struct slre *r, int code)
+{
+ if (r->code_size >= (int) (sizeof(r->code) / sizeof(r->code[0])))
+ r->err_str = "RE is too long (code overflow)";
+ else
+ r->code[r->code_size++] = (unsigned char) code;
+}
+
+static void
+store_char_in_data(struct slre *r, int ch)
+{
+ if (r->data_size >= (int) sizeof(r->data))
+ r->err_str = "RE is too long (data overflow)";
+ else
+ r->data[r->data_size++] = ch;
+}
+
+static void
+exact(struct slre *r, const char **re)
+{
+ int old_data_size = r->data_size;
+
+ while (**re != '\0' && (strchr(meta_chars, **re)) == NULL)
+ store_char_in_data(r, *(*re)++);
+
+ emit(r, EXACT);
+ emit(r, old_data_size);
+ emit(r, r->data_size - old_data_size);
+}
+
+static int
+get_escape_char(const char **re)
+{
+ int res;
+
+ switch (*(*re)++) {
+ case 'n':
+ res = '\n';
+ break;
+ case 'r':
+ res = '\r';
+ break;
+ case 't':
+ res = '\t';
+ break;
+ case '0':
+ res = 0;
+ break;
+ case 'S':
+ res = NONSPACE << 8;
+ break;
+ case 's':
+ res = SPACE << 8;
+ break;
+ case 'd':
+ res = DIGIT << 8;
+ break;
+ default:
+ res = (*re)[-1];
+ break;
+ }
+
+ return res;
+}
+
+static void
+anyof(struct slre *r, const char **re)
+{
+ int esc, old_data_size = r->data_size, op = ANYOF;
+
+ if (**re == '^') {
+ op = ANYBUT;
+ (*re)++;
+ }
+
+ while (**re != '\0')
+
+ switch (*(*re)++) {
+ case ']':
+ emit(r, op);
+ emit(r, old_data_size);
+ emit(r, r->data_size - old_data_size);
+ return;
+ /* NOTREACHED */
+ break;
+ case '\\':
+ esc = get_escape_char(re);
+ if ((esc & 0xff) == 0) {
+ store_char_in_data(r, 0);
+ store_char_in_data(r, esc >> 8);
+ } else {
+ store_char_in_data(r, esc);
+ }
+ break;
+ default:
+ store_char_in_data(r, (*re)[-1]);
+ break;
+ }
+
+ r->err_str = "No closing ']' bracket";
+}
+
+static void
+relocate(struct slre *r, int begin, int shift)
+{
+ emit(r, END);
+ memmove(r->code + begin + shift, r->code + begin, r->code_size - begin);
+ r->code_size += shift;
+}
+
+static void
+quantifier(struct slre *r, int prev, int op)
+{
+ if (r->code[prev] == EXACT && r->code[prev + 2] > 1) {
+ r->code[prev + 2]--;
+ emit(r, EXACT);
+ emit(r, r->code[prev + 1] + r->code[prev + 2]);
+ emit(r, 1);
+ prev = r->code_size - 3;
+ }
+ relocate(r, prev, 2);
+ r->code[prev] = op;
+ set_jump_offset(r, prev + 1, prev);
+}
+
+static void
+exact_one_char(struct slre *r, int ch)
+{
+ emit(r, EXACT);
+ emit(r, r->data_size);
+ emit(r, 1);
+ store_char_in_data(r, ch);
+}
+
+static void
+fixup_branch(struct slre *r, int fixup)
+{
+ if (fixup > 0) {
+ emit(r, END);
+ set_jump_offset(r, fixup, fixup - 2);
+ }
+}
+
+static void
+compile(struct slre *r, const char **re)
+{
+ int op, esc, branch_start, last_op, fixup, cap_no, level;
+
+ fixup = 0;
+ level = r->num_caps;
+ branch_start = last_op = r->code_size;
+
+ for (;;)
+ switch (*(*re)++) {
+ case '\0':
+ (*re)--;
+ return;
+ /* NOTREACHED */
+ break;
+ case '^':
+ emit(r, BOL);
+ break;
+ case '$':
+ emit(r, EOL);
+ break;
+ case '.':
+ last_op = r->code_size;
+ emit(r, ANY);
+ break;
+ case '[':
+ last_op = r->code_size;
+ anyof(r, re);
+ break;
+ case '\\':
+ last_op = r->code_size;
+ esc = get_escape_char(re);
+ if (esc & 0xff00)
+ emit(r, esc >> 8);
+ else
+ exact_one_char(r, esc);
+ break;
+ case '(':
+ last_op = r->code_size;
+ cap_no = ++r->num_caps;
+ emit(r, OPEN);
+ emit(r, cap_no);
+
+ compile(r, re);
+ if (*(*re)++ != ')') {
+ r->err_str = "No closing bracket";
+ return;
+ }
+
+ emit(r, CLOSE);
+ emit(r, cap_no);
+ break;
+ case ')':
+ (*re)--;
+ fixup_branch(r, fixup);
+ if (level == 0) {
+ r->err_str = "Unbalanced brackets";
+ return;
+ }
+ return;
+ /* NOTREACHED */
+ break;
+ case '+':
+ case '*':
+ op = (*re)[-1] == '*' ? STAR : PLUS;
+ if (**re == '?') {
+ (*re)++;
+ op = op == STAR ? STARQ : PLUSQ;
+ }
+ quantifier(r, last_op, op);
+ break;
+ case '?':
+ quantifier(r, last_op, QUEST);
+ break;
+ case '|':
+ fixup_branch(r, fixup);
+ relocate(r, branch_start, 3);
+ r->code[branch_start] = BRANCH;
+ set_jump_offset(r, branch_start + 1, branch_start);
+ fixup = branch_start + 2;
+ r->code[fixup] = 0xff;
+ break;
+ default:
+ (*re)--;
+ last_op = r->code_size;
+ exact(r, re);
+ break;
+ }
+}
+
+int
+slre_compile(struct slre *r, const char *re)
+{
+ r->err_str = NULL;
+ r->code_size = r->data_size = r->num_caps = r->anchored = 0;
+
+ if (*re == '^')
+ r->anchored++;
+
+ emit(r, OPEN); /* This will capture what matches full RE */
+ emit(r, 0);
+
+ while (*re != '\0')
+ compile(r, &re);
+
+ if (r->code[2] == BRANCH)
+ fixup_branch(r, 4);
+
+ emit(r, CLOSE);
+ emit(r, 0);
+ emit(r, END);
+
+ return (r->err_str == NULL ? 1 : 0);
+}
+
+static int match(const struct slre *, int,
+ const char *, int, int *, struct cap *);
+
+static void
+loop_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+ int saved_offset, matched_offset;
+
+ matched_offset = *ofs;
+
+ while (match(r, pc + 2, s, len, ofs, NULL)) {
+ saved_offset = *ofs;
+ if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+ matched_offset = saved_offset;
+ *ofs = saved_offset;
+ }
+
+ *ofs = matched_offset;
+}
+
+static void
+loop_non_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+ int saved_offset = *ofs;
+
+ while (match(r, pc + 2, s, len, ofs, NULL)) {
+ saved_offset = *ofs;
+ if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+ break;
+ }
+
+ *ofs = saved_offset;
+}
+
+static int
+is_any_of(const unsigned char *p, int len, const char *s, int *ofs)
+{
+ int i, ch;
+
+ ch = s[*ofs];
+
+ for (i = 0; i < len; i++)
+ if (p[i] == ch) {
+ (*ofs)++;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+is_any_but(const unsigned char *p, int len, const char *s, int *ofs)
+{
+ int i, ch;
+
+ ch = s[*ofs];
+
+ for (i = 0; i < len; i++) {
+ if (p[i] == ch)
+ return 0;
+ }
+
+ (*ofs)++;
+ return 1;
+}
+
+static int
+match(const struct slre *r, int pc, const char *s, int len,
+ int *ofs, struct cap *caps)
+{
+ int n, saved_offset, res = 1;
+
+ while (res && r->code[pc] != END) {
+
+ assert(pc < r->code_size);
+ assert(pc < (int) (sizeof(r->code) / sizeof(r->code[0])));
+
+ switch (r->code[pc]) {
+ case BRANCH:
+ saved_offset = *ofs;
+ res = match(r, pc + 3, s, len, ofs, caps);
+ if (res == 0) {
+ *ofs = saved_offset;
+ res = match(r, pc + r->code[pc + 1],
+ s, len, ofs, caps);
+ }
+ pc += r->code[pc + 2];
+ break;
+ case EXACT:
+ res = 0;
+ n = r->code[pc + 2]; /* String length */
+ if (n <= len - *ofs && !memcmp(s + *ofs, r->data +
+ r->code[pc + 1], n)) {
+ (*ofs) += n;
+ res = 1;
+ }
+ pc += 3;
+ break;
+ case QUEST:
+ res = 1;
+ saved_offset = *ofs;
+ if (!match(r, pc + 2, s, len, ofs, caps))
+ *ofs = saved_offset;
+ pc += r->code[pc + 1];
+ break;
+ case STAR:
+ res = 1;
+ loop_greedy(r, pc, s, len, ofs);
+ pc += r->code[pc + 1];
+ break;
+ case STARQ:
+ res = 1;
+ loop_non_greedy(r, pc, s, len, ofs);
+ pc += r->code[pc + 1];
+ break;
+ case PLUS:
+ res = match(r, pc + 2, s, len, ofs, caps);
+ if (res == 0)
+ break;
+
+ loop_greedy(r, pc, s, len, ofs);
+ pc += r->code[pc + 1];
+ break;
+ case PLUSQ:
+ res = match(r, pc + 2, s, len, ofs, caps);
+ if (res == 0)
+ break;
+
+ loop_non_greedy(r, pc, s, len, ofs);
+ pc += r->code[pc + 1];
+ break;
+ case SPACE:
+ res = 0;
+ if (*ofs < len && isspace(((unsigned char *)s)[*ofs])) {
+ (*ofs)++;
+ res = 1;
+ }
+ pc++;
+ break;
+ case NONSPACE:
+ res = 0;
+ if (*ofs < len &&
+ !isspace(((unsigned char *)s)[*ofs])) {
+ (*ofs)++;
+ res = 1;
+ }
+ pc++;
+ break;
+ case DIGIT:
+ res = 0;
+ if (*ofs < len && isdigit(((unsigned char *)s)[*ofs])) {
+ (*ofs)++;
+ res = 1;
+ }
+ pc++;
+ break;
+ case ANY:
+ res = 0;
+ if (*ofs < len) {
+ (*ofs)++;
+ res = 1;
+ }
+ pc++;
+ break;
+ case ANYOF:
+ res = 0;
+ if (*ofs < len)
+ res = is_any_of(r->data + r->code[pc + 1],
+ r->code[pc + 2], s, ofs);
+ pc += 3;
+ break;
+ case ANYBUT:
+ res = 0;
+ if (*ofs < len)
+ res = is_any_but(r->data + r->code[pc + 1],
+ r->code[pc + 2], s, ofs);
+ pc += 3;
+ break;
+ case BOL:
+ res = *ofs == 0 ? 1 : 0;
+ pc++;
+ break;
+ case EOL:
+ res = *ofs == len ? 1 : 0;
+ pc++;
+ break;
+ case OPEN:
+ if (caps != NULL)
+ caps[r->code[pc + 1]].ptr = s + *ofs;
+ pc += 2;
+ break;
+ case CLOSE:
+ if (caps != NULL)
+ caps[r->code[pc + 1]].len = (s + *ofs) -
+ caps[r->code[pc + 1]].ptr;
+ pc += 2;
+ break;
+ case END:
+ pc++;
+ break;
+ default:
+ printf("unknown cmd (%d) at %d\n", r->code[pc], pc);
+ assert(0);
+ break;
+ }
+ }
+
+ return res;
+}
+
+int
+slre_match(const struct slre *r, const char *buf, int len,
+ struct cap *caps)
+{
+ int i, ofs = 0, res = 0;
+
+ if (r->anchored) {
+ res = match(r, 0, buf, len, &ofs, caps);
+ } else {
+ for (i = 0; i < len && res == 0; i++) {
+ ofs = i;
+ res = match(r, 0, buf, len, &ofs, caps);
+ }
+ }
+
+ return res;
+}
+
+#ifdef SLRE_TEST
+#define N_CAPS 5
+
+int main(int argc, char *argv[])
+{
+ struct slre slre;
+ struct cap caps[N_CAPS];
+ unsigned char data[1 * 1024 * 1024];
+ FILE *fp;
+ int i, res, len;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s 'slre' <file>\n", argv[0]);
+ return 1;
+ }
+
+ fp = fopen(argv[2], "rb");
+ if (fp == NULL) {
+ fprintf(stderr, "Error: cannot open %s:%s\n",
+ argv[2], strerror(errno));
+ return 1;
+ }
+
+ if (!slre_compile(&slre, argv[1])) {
+ fprintf(stderr, "Error compiling slre: %s\n", slre.err_str);
+ return 1;
+ }
+
+ slre_dump(&slre, stderr);
+
+ while (fgets(data, sizeof(data), fp) != NULL) {
+ len = strlen(data);
+
+ if ((len > 0) && (data[len-1] == '\n')) {
+ data[len-1] = '\0';
+ --len;
+ }
+
+ printf("Data = \"%s\"\n", data);
+
+ (void) memset(caps, 0, sizeof(caps));
+
+ res = slre_match(&slre, data, len, caps);
+ printf("Result [%d]: %d\n", i, res);
+
+ for (i = 0; i < N_CAPS; i++) {
+ if (caps[i].len > 0) {
+ printf("Substring %d: len=%d [%.*s]\n", i,
+ caps[i].len,
+ caps[i].len, caps[i].ptr);
+ }
+ }
+ printf("----------------------------------------------------\n");
+ }
+ (void) fclose(fp);
+
+ return 0;
+}
+#endif /* SLRE_TEST */
diff --git a/lib/smbios.c b/lib/smbios.c
new file mode 100644
index 00000000..7b74971f
--- /dev/null
+++ b/lib/smbios.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Adapted from coreboot src/arch/x86/smbios.c
+ */
+
+#include <common.h>
+#include <env.h>
+#include <mapmem.h>
+#include <smbios.h>
+#include <tables_csum.h>
+#include <version.h>
+#ifdef CONFIG_CPU
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#endif
+
+/**
+ * smbios_add_string() - add a string to the string area
+ *
+ * This adds a string to the string area which is appended directly after
+ * the formatted portion of an SMBIOS structure.
+ *
+ * @start: string area start address
+ * @str: string to add
+ * @return: string number in the string area
+ */
+static int smbios_add_string(char *start, const char *str)
+{
+ int i = 1;
+ char *p = start;
+
+ for (;;) {
+ if (!*p) {
+ strcpy(p, str);
+ p += strlen(str);
+ *p++ = '\0';
+ *p++ = '\0';
+
+ return i;
+ }
+
+ if (!strcmp(p, str))
+ return i;
+
+ p += strlen(p) + 1;
+ i++;
+ }
+}
+
+/**
+ * smbios_string_table_len() - compute the string area size
+ *
+ * This computes the size of the string area including the string terminator.
+ *
+ * @start: string area start address
+ * @return: string area size
+ */
+static int smbios_string_table_len(char *start)
+{
+ char *p = start;
+ int i, len = 0;
+
+ while (*p) {
+ i = strlen(p) + 1;
+ p += i;
+ len += i;
+ }
+
+ return len + 1;
+}
+
+static int smbios_write_type0(ulong *current, int handle)
+{
+ struct smbios_type0 *t;
+ int len = sizeof(struct smbios_type0);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type0));
+ fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
+ t->vendor = smbios_add_string(t->eos, "U-Boot");
+ t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
+ t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
+#ifdef CONFIG_ROM_SIZE
+ t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
+#endif
+ t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
+ BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
+ BIOS_CHARACTERISTICS_UPGRADEABLE;
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+ t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
+#endif
+#ifdef CONFIG_EFI_LOADER
+ t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
+#endif
+ t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
+
+ t->bios_major_release = 0xff;
+ t->bios_minor_release = 0xff;
+ t->ec_major_release = 0xff;
+ t->ec_minor_release = 0xff;
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type1(ulong *current, int handle)
+{
+ struct smbios_type1 *t;
+ int len = sizeof(struct smbios_type1);
+ char *serial_str = env_get("serial#");
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type1));
+ fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
+ t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
+ t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
+ if (serial_str) {
+ strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
+ t->serial_number = smbios_add_string(t->eos, serial_str);
+ }
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type2(ulong *current, int handle)
+{
+ struct smbios_type2 *t;
+ int len = sizeof(struct smbios_type2);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type2));
+ fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
+ t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
+ t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
+ t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
+ t->board_type = SMBIOS_BOARD_MOTHERBOARD;
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type3(ulong *current, int handle)
+{
+ struct smbios_type3 *t;
+ int len = sizeof(struct smbios_type3);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type3));
+ fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
+ t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
+ t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
+ t->bootup_state = SMBIOS_STATE_SAFE;
+ t->power_supply_state = SMBIOS_STATE_SAFE;
+ t->thermal_state = SMBIOS_STATE_SAFE;
+ t->security_status = SMBIOS_SECURITY_NONE;
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static void smbios_write_type4_dm(struct smbios_type4 *t)
+{
+ u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
+ const char *vendor = "Unknown";
+ const char *name = "Unknown";
+
+#ifdef CONFIG_CPU
+ char processor_name[49];
+ char vendor_name[49];
+ struct udevice *dev = NULL;
+
+ uclass_find_first_device(UCLASS_CPU, &dev);
+ if (dev) {
+ struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+ if (plat->family)
+ processor_family = plat->family;
+ t->processor_id[0] = plat->id[0];
+ t->processor_id[1] = plat->id[1];
+
+ if (!cpu_get_vendor(dev, vendor_name, sizeof(vendor_name)))
+ vendor = vendor_name;
+ if (!cpu_get_desc(dev, processor_name, sizeof(processor_name)))
+ name = processor_name;
+ }
+#endif
+
+ t->processor_family = processor_family;
+ t->processor_manufacturer = smbios_add_string(t->eos, vendor);
+ t->processor_version = smbios_add_string(t->eos, name);
+}
+
+static int smbios_write_type4(ulong *current, int handle)
+{
+ struct smbios_type4 *t;
+ int len = sizeof(struct smbios_type4);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type4));
+ fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
+ t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
+ smbios_write_type4_dm(t);
+ t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
+ t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
+ t->l1_cache_handle = 0xffff;
+ t->l2_cache_handle = 0xffff;
+ t->l3_cache_handle = 0xffff;
+ t->processor_family2 = t->processor_family;
+
+ len = t->length + smbios_string_table_len(t->eos);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type32(ulong *current, int handle)
+{
+ struct smbios_type32 *t;
+ int len = sizeof(struct smbios_type32);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type32));
+ fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
+
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type127(ulong *current, int handle)
+{
+ struct smbios_type127 *t;
+ int len = sizeof(struct smbios_type127);
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, sizeof(struct smbios_type127));
+ fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
+
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static smbios_write_type smbios_write_funcs[] = {
+ smbios_write_type0,
+ smbios_write_type1,
+ smbios_write_type2,
+ smbios_write_type3,
+ smbios_write_type4,
+ smbios_write_type32,
+ smbios_write_type127
+};
+
+ulong write_smbios_table(ulong addr)
+{
+ struct smbios_entry *se;
+ ulong table_addr;
+ ulong tables;
+ int len = 0;
+ int max_struct_size = 0;
+ int handle = 0;
+ char *istart;
+ int isize;
+ int i;
+
+ /* 16 byte align the table address */
+ addr = ALIGN(addr, 16);
+
+ se = map_sysmem(addr, sizeof(struct smbios_entry));
+ memset(se, 0, sizeof(struct smbios_entry));
+
+ addr += sizeof(struct smbios_entry);
+ addr = ALIGN(addr, 16);
+ tables = addr;
+
+ /* populate minimum required tables */
+ for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
+ int tmp = smbios_write_funcs[i]((ulong *)&addr, handle++);
+
+ max_struct_size = max(max_struct_size, tmp);
+ len += tmp;
+ }
+
+ memcpy(se->anchor, "_SM_", 4);
+ se->length = sizeof(struct smbios_entry);
+ se->major_ver = SMBIOS_MAJOR_VER;
+ se->minor_ver = SMBIOS_MINOR_VER;
+ se->max_struct_size = max_struct_size;
+ memcpy(se->intermediate_anchor, "_DMI_", 5);
+ se->struct_table_length = len;
+
+ /*
+ * We must use a pointer here so things work correctly on sandbox. The
+ * user of this table is not aware of the mapping of addresses to
+ * sandbox's DRAM buffer.
+ */
+ table_addr = (ulong)map_sysmem(tables, 0);
+ if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
+ /*
+ * We need to put this >32-bit pointer into the table but the
+ * field is only 32 bits wide.
+ */
+ printf("WARNING: SMBIOS table_address overflow %llx\n",
+ (unsigned long long)table_addr);
+ table_addr = 0;
+ }
+ se->struct_table_address = table_addr;
+
+ se->struct_count = handle;
+
+ /* calculate checksums */
+ istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
+ isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
+ se->intermediate_checksum = table_compute_checksum(istart, isize);
+ se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
+ unmap_sysmem(se);
+
+ return addr;
+}
diff --git a/lib/string.c b/lib/string.c
new file mode 100644
index 00000000..9b779ddc
--- /dev/null
+++ b/lib/string.c
@@ -0,0 +1,729 @@
+/*
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * - Added strsep() which will replace strtok() soon (because strsep() is
+ * reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+
+
+/**
+ * strncasecmp - Case insensitive, length-limited string comparison
+ * @s1: One string
+ * @s2: The other string
+ * @len: the maximum number of characters to compare
+ */
+int strncasecmp(const char *s1, const char *s2, size_t len)
+{
+ /* Yes, Virginia, it had better be unsigned */
+ unsigned char c1, c2;
+
+ c1 = 0; c2 = 0;
+ if (len) {
+ do {
+ c1 = *s1; c2 = *s2;
+ s1++; s2++;
+ if (!c1)
+ break;
+ if (!c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = tolower(c1);
+ c2 = tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
+ }
+ return (int)c1 - (int)c2;
+}
+
+/**
+ * strcasecmp - Case insensitive string comparison
+ * @s1: One string
+ * @s2: The other string
+ */
+int strcasecmp(const char *s1, const char *s2)
+{
+ return strncasecmp(s1, s2, -1U);
+}
+
+char * ___strtok;
+
+#ifndef __HAVE_ARCH_STRCPY
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCPY
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRLCPY
+/**
+ * strlcpy - Copy a C-string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ */
+size_t strlcpy(char *dest, const char *src, size_t size)
+{
+ size_t ret = strlen(src);
+
+ if (size) {
+ size_t len = (ret >= size) ? size - 1 : ret;
+ memcpy(dest, src, len);
+ dest[len] = '\0';
+ }
+ return ret;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCAT
+/**
+ * strcat - Append one %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ */
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCAT
+/**
+ * strncat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The maximum numbers of bytes to copy
+ *
+ * Note that in contrast to strncpy, strncat ensures the result is
+ * terminated.
+ */
+char * strncat(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ if (count) {
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++)) {
+ if (--count == 0) {
+ *dest = '\0';
+ break;
+ }
+ }
+ }
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCMP
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCMP
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCHR
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *) s;
+}
+#endif
+
+const char *strchrnul(const char *s, int c)
+{
+ for (; *s != (char)c; ++s)
+ if (*s == '\0')
+ break;
+ return s;
+}
+
+#ifndef __HAVE_ARCH_STRRCHR
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRLEN
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNLEN
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCSPN
+/**
+ * strcspn - Calculate the length of the initial substring of @s which does
+ * not contain letters in @reject
+ * @s: The string to be searched
+ * @reject: The string to avoid
+ */
+size_t strcspn(const char *s, const char *reject)
+{
+ const char *p;
+ const char *r;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (r = reject; *r != '\0'; ++r) {
+ if (*p == *r)
+ return count;
+ }
+ ++count;
+ }
+ return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRDUP
+char * strdup(const char *s)
+{
+ char *new;
+
+ if ((s == NULL) ||
+ ((new = malloc (strlen(s) + 1)) == NULL) ) {
+ return NULL;
+ }
+
+ strcpy (new, s);
+ return new;
+}
+#endif
+
+char * strndup(const char *s, size_t n)
+{
+ size_t len;
+ char *new;
+
+ if (s == NULL)
+ return NULL;
+
+ len = strlen(s);
+
+ if (n < len)
+ len = n;
+
+ new = malloc(len + 1);
+ if (new == NULL)
+ return NULL;
+
+ strncpy(new, s, len);
+ new[len] = '\0';
+
+ return new;
+}
+
+#ifndef __HAVE_ARCH_STRSPN
+/**
+ * strspn - Calculate the length of the initial substring of @s which only
+ * contain letters in @accept
+ * @s: The string to be searched
+ * @accept: The string to search for
+ */
+size_t strspn(const char *s, const char *accept)
+{
+ const char *p;
+ const char *a;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (a = accept; *a != '\0'; ++a) {
+ if (*p == *a)
+ break;
+ }
+ if (*a == '\0')
+ return count;
+ ++count;
+ }
+
+ return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRPBRK
+/**
+ * strpbrk - Find the first occurrence of a set of characters
+ * @cs: The string to be searched
+ * @ct: The characters to search for
+ */
+char * strpbrk(const char * cs,const char * ct)
+{
+ const char *sc1,*sc2;
+
+ for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+ for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+ if (*sc1 == *sc2)
+ return (char *) sc1;
+ }
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRTOK
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char * strtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : ___strtok;
+ if (!sbegin) {
+ return NULL;
+ }
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0') {
+ ___strtok = NULL;
+ return( NULL );
+ }
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+ ___strtok = send;
+ return (sbegin);
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSEP
+/**
+ * strsep - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * strsep() updates @s to point after the token, ready for the next call.
+ *
+ * It returns empty tokens, too, behaving exactly like the libc function
+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
+ * Same semantics, slimmer shape. ;)
+ */
+char * strsep(char **s, const char *ct)
+{
+ char *sbegin = *s, *end;
+
+ if (sbegin == NULL)
+ return NULL;
+
+ end = strpbrk(sbegin, ct);
+ if (end)
+ *end++ = '\0';
+ *s = end;
+
+ return sbegin;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSWAB
+/**
+ * strswab - swap adjacent even and odd bytes in %NUL-terminated string
+ * s: address of the string
+ *
+ * returns the address of the swapped string or NULL on error. If
+ * string length is odd, last byte is untouched.
+ */
+char *strswab(const char *s)
+{
+ char *p, *q;
+
+ if ((NULL == s) || ('\0' == *s)) {
+ return (NULL);
+ }
+
+ for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) {
+ char tmp;
+
+ tmp = *p;
+ *p = *q;
+ *q = tmp;
+ }
+
+ return (char *) s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSET
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+ unsigned long *sl = (unsigned long *) s;
+ char *s8;
+
+#if !CONFIG_IS_ENABLED(TINY_MEMSET)
+ unsigned long cl = 0;
+ int i;
+
+ /* do it one word at a time (32 bits or 64 bits) while possible */
+ if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
+ for (i = 0; i < sizeof(*sl); i++) {
+ cl <<= 8;
+ cl |= c & 0xff;
+ }
+ while (count >= sizeof(*sl)) {
+ *sl++ = cl;
+ count -= sizeof(*sl);
+ }
+ }
+#endif /* fill 8 bits at a time */
+ s8 = (char *)sl;
+ while (count--)
+ *s8++ = c;
+
+ return s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCPY
+/**
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+void * memcpy(void *dest, const void *src, size_t count)
+{
+ unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
+ char *d8, *s8;
+
+ if (src == dest)
+ return dest;
+
+ /* while all data is aligned (common case), copy a word at a time */
+ if ( (((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) {
+ while (count >= sizeof(*dl)) {
+ *dl++ = *sl++;
+ count -= sizeof(*dl);
+ }
+ }
+ /* copy the reset one byte at a time */
+ d8 = (char *)dl;
+ s8 = (char *)sl;
+ while (count--)
+ *d8++ = *s8++;
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMMOVE
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+ char *tmp, *s;
+
+ if (dest <= src) {
+ memcpy(dest, src, count);
+ } else {
+ tmp = (char *) dest + count;
+ s = (char *) src + count;
+ while (count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCMP
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSCAN
+/**
+ * memscan - Find a character in an area of memory.
+ * @addr: The memory area
+ * @c: The byte to search for
+ * @size: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or 1 byte past
+ * the area if @c is not found
+ */
+void * memscan(void * addr, int c, size_t size)
+{
+ unsigned char * p = (unsigned char *) addr;
+
+ while (size) {
+ if (*p == c)
+ return (void *) p;
+ p++;
+ size--;
+ }
+ return (void *) p;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSTR
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char * strstr(const char * s1,const char * s2)
+{
+ int l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return (char *) s1;
+ s1++;
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCHR
+/**
+ * memchr - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or %NULL
+ * if @c is not found
+ */
+void *memchr(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ while (n-- != 0) {
+ if ((unsigned char)c == *p++) {
+ return (void *)(p-1);
+ }
+ }
+ return NULL;
+}
+
+#endif
+#ifndef __HAVE_ARCH_MEMCHR_INV
+static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
+{
+ while (bytes) {
+ if (*start != value)
+ return (void *)start;
+ start++;
+ bytes--;
+ }
+ return NULL;
+}
+/**
+ * memchr_inv - Find an unmatching character in an area of memory.
+ * @start: The memory area
+ * @c: Find a character other than c
+ * @bytes: The size of the area.
+ *
+ * returns the address of the first character other than @c, or %NULL
+ * if the whole buffer contains just @c.
+ */
+void *memchr_inv(const void *start, int c, size_t bytes)
+{
+ u8 value = c;
+ u64 value64;
+ unsigned int words, prefix;
+
+ if (bytes <= 16)
+ return check_bytes8(start, value, bytes);
+
+ value64 = value;
+ value64 |= value64 << 8;
+ value64 |= value64 << 16;
+ value64 |= value64 << 32;
+
+ prefix = (unsigned long)start % 8;
+ if (prefix) {
+ u8 *r;
+
+ prefix = 8 - prefix;
+ r = check_bytes8(start, value, prefix);
+ if (r)
+ return r;
+ start += prefix;
+ bytes -= prefix;
+ }
+
+ words = bytes / 8;
+
+ while (words) {
+ if (*(u64 *)start != value64)
+ return check_bytes8(start, value, 8);
+ start += 8;
+ words--;
+ }
+
+ return check_bytes8(start, value, bytes % 8);
+}
+#endif
diff --git a/lib/strto.c b/lib/strto.c
new file mode 100644
index 00000000..55ff9f74
--- /dev/null
+++ b/lib/strto.c
@@ -0,0 +1,165 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <linux/ctype.h>
+
+/* from lib/kstrtox.c */
+static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
+{
+ if (*base == 0) {
+ if (s[0] == '0') {
+ if (tolower(s[1]) == 'x' && isxdigit(s[2]))
+ *base = 16;
+ else
+ *base = 8;
+ } else
+ *base = 10;
+ }
+ if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
+ s += 2;
+ return s;
+}
+
+unsigned long simple_strtoul(const char *cp, char **endp,
+ unsigned int base)
+{
+ unsigned long result = 0;
+ unsigned long value;
+
+ cp = _parse_integer_fixup_radix(cp, &base);
+
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+
+ if (endp)
+ *endp = (char *)cp;
+
+ return result;
+}
+
+int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
+{
+ char *tail;
+ unsigned long val;
+ size_t len;
+
+ *res = 0;
+ len = strlen(cp);
+ if (len == 0)
+ return -EINVAL;
+
+ val = simple_strtoul(cp, &tail, base);
+ if (tail == cp)
+ return -EINVAL;
+
+ if ((*tail == '\0') ||
+ ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
+ *res = val;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+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);
+}
+
+unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
+{
+ unsigned long result = simple_strtoul(cp, endp, base);
+ switch (tolower(**endp)) {
+ case 'g':
+ result *= 1024;
+ /* fall through */
+ case 'm':
+ result *= 1024;
+ /* fall through */
+ case 'k':
+ result *= 1024;
+ (*endp)++;
+ if (**endp == 'i')
+ (*endp)++;
+ if (**endp == 'B')
+ (*endp)++;
+ }
+ return result;
+}
+
+unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
+{
+ unsigned long long result = simple_strtoull(cp, endp, base);
+ switch (tolower(**endp)) {
+ case 'g':
+ result *= 1024;
+ /* fall through */
+ case 'm':
+ result *= 1024;
+ /* fall through */
+ case 'k':
+ result *= 1024;
+ (*endp)++;
+ if (**endp == 'i')
+ (*endp)++;
+ if (**endp == 'B')
+ (*endp)++;
+ }
+ return result;
+}
+
+unsigned long long simple_strtoull(const char *cp, char **endp,
+ unsigned int base)
+{
+ unsigned long long result = 0, value;
+
+ cp = _parse_integer_fixup_radix(cp, &base);
+
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
+ : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
+ result = result * base + value;
+ cp++;
+ }
+
+ if (endp)
+ *endp = (char *) cp;
+
+ return result;
+}
+
+long trailing_strtoln(const char *str, const char *end)
+{
+ const char *p;
+
+ if (!end)
+ end = str + strlen(str);
+ if (isdigit(end[-1])) {
+ for (p = end - 1; p > str; p--) {
+ if (!isdigit(*p))
+ return simple_strtoul(p + 1, NULL, 10);
+ }
+ }
+
+ return -1;
+}
+
+long trailing_strtol(const char *str)
+{
+ return trailing_strtoln(str, NULL);
+}
diff --git a/lib/tables_csum.c b/lib/tables_csum.c
new file mode 100644
index 00000000..e2630d57
--- /dev/null
+++ b/lib/tables_csum.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <linux/ctype.h>
+
+u8 table_compute_checksum(void *v, int len)
+{
+ u8 *bytes = v;
+ u8 checksum = 0;
+ int i;
+
+ for (i = 0; i < len; i++)
+ checksum -= bytes[i];
+
+ return checksum;
+}
diff --git a/lib/time.c b/lib/time.c
new file mode 100644
index 00000000..75de48f9
--- /dev/null
+++ b/lib/time.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <time.h>
+#include <timer.h>
+#include <watchdog.h>
+#include <div64.h>
+#include <asm/io.h>
+
+#ifndef CONFIG_WD_PERIOD
+# define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_TIMER_RATE
+/* Returns tick rate in ticks per second */
+ulong notrace get_tbclk(void)
+{
+ return CONFIG_SYS_TIMER_RATE;
+}
+#endif
+
+#ifdef CONFIG_SYS_TIMER_COUNTER
+unsigned long notrace timer_read_counter(void)
+{
+#ifdef CONFIG_SYS_TIMER_COUNTS_DOWN
+ return ~readl(CONFIG_SYS_TIMER_COUNTER);
+#else
+ return readl(CONFIG_SYS_TIMER_COUNTER);
+#endif
+}
+
+ulong timer_get_boot_us(void)
+{
+ ulong count = timer_read_counter();
+
+#if CONFIG_SYS_TIMER_RATE == 1000000
+ return count;
+#elif CONFIG_SYS_TIMER_RATE > 1000000
+ return lldiv(count, CONFIG_SYS_TIMER_RATE / 1000000);
+#elif defined(CONFIG_SYS_TIMER_RATE)
+ return (unsigned long long)count * 1000000 / CONFIG_SYS_TIMER_RATE;
+#else
+ /* Assume the counter is in microseconds */
+ return count;
+#endif
+}
+
+#else
+extern unsigned long __weak timer_read_counter(void);
+#endif
+
+#if CONFIG_IS_ENABLED(TIMER)
+ulong notrace get_tbclk(void)
+{
+ if (!gd->timer) {
+#ifdef CONFIG_TIMER_EARLY
+ return timer_early_get_rate();
+#else
+ int ret;
+
+ ret = dm_timer_init();
+ if (ret)
+ return ret;
+#endif
+ }
+
+ return timer_get_rate(gd->timer);
+}
+
+uint64_t notrace get_ticks(void)
+{
+ u64 count;
+ int ret;
+
+ if (!gd->timer) {
+#ifdef CONFIG_TIMER_EARLY
+ return timer_early_get_count();
+#else
+ int ret;
+
+ ret = dm_timer_init();
+ if (ret)
+ return ret;
+#endif
+ }
+
+ ret = timer_get_count(gd->timer, &count);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+#else /* !CONFIG_TIMER */
+
+uint64_t __weak notrace get_ticks(void)
+{
+ unsigned long now = timer_read_counter();
+
+ /* increment tbu if tbl has rolled over */
+ if (now < gd->timebase_l)
+ gd->timebase_h++;
+ gd->timebase_l = now;
+ return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
+}
+
+#endif /* CONFIG_TIMER */
+
+/* Returns time in milliseconds */
+static uint64_t notrace tick_to_time(uint64_t tick)
+{
+ ulong div = get_tbclk();
+
+ tick *= CONFIG_SYS_HZ;
+ do_div(tick, div);
+ return tick;
+}
+
+int __weak timer_init(void)
+{
+ return 0;
+}
+
+/* Returns time in milliseconds */
+ulong __weak get_timer(ulong base)
+{
+ return tick_to_time(get_ticks()) - base;
+}
+
+static uint64_t notrace tick_to_time_us(uint64_t tick)
+{
+ ulong div = get_tbclk() / 1000;
+
+ tick *= CONFIG_SYS_HZ;
+ do_div(tick, div);
+ return tick;
+}
+
+uint64_t __weak get_timer_us(uint64_t base)
+{
+ return tick_to_time_us(get_ticks()) - base;
+}
+
+unsigned long __weak notrace timer_get_us(void)
+{
+ return tick_to_time(get_ticks() * 1000);
+}
+
+uint64_t usec_to_tick(unsigned long usec)
+{
+ uint64_t tick = usec;
+ tick *= get_tbclk();
+ do_div(tick, 1000000);
+ return tick;
+}
+
+void __weak __udelay(unsigned long usec)
+{
+ uint64_t tmp;
+
+ tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */
+
+ while (get_ticks() < tmp+1) /* loop till event */
+ /*NOP*/;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void udelay(unsigned long usec)
+{
+ ulong kv;
+
+ do {
+ WATCHDOG_RESET();
+ kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
+ __udelay (kv);
+ usec -= kv;
+ } while(usec);
+}
diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c
new file mode 100644
index 00000000..1138c701
--- /dev/null
+++ b/lib/tiny-printf.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * Tiny printf version for SPL
+ *
+ * Copied from:
+ * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
+ *
+ * Copyright (C) 2004,2008 Kustaa Nyholm
+ */
+
+#include <common.h>
+#include <stdarg.h>
+#include <serial.h>
+#include <linux/ctype.h>
+
+struct printf_info {
+ char *bf; /* Digit buffer */
+ char zs; /* non-zero if a digit has been written */
+ char *outstr; /* Next output position for sprintf() */
+
+ /* Output a character */
+ void (*putc)(struct printf_info *info, char ch);
+};
+
+static void out(struct printf_info *info, char c)
+{
+ *info->bf++ = c;
+}
+
+static void out_dgt(struct printf_info *info, char dgt)
+{
+ out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
+ info->zs = 1;
+}
+
+static void div_out(struct printf_info *info, unsigned long *num,
+ unsigned long div)
+{
+ unsigned char dgt = 0;
+
+ while (*num >= div) {
+ *num -= div;
+ dgt++;
+ }
+
+ if (info->zs || dgt > 0)
+ out_dgt(info, dgt);
+}
+
+#ifdef CONFIG_SPL_NET_SUPPORT
+static void string(struct printf_info *info, char *s)
+{
+ char ch;
+
+ while ((ch = *s++))
+ out(info, ch);
+}
+
+static 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, u8 byte)
+{
+ *buf++ = hex_asc_hi(byte);
+ *buf++ = hex_asc_lo(byte);
+ return buf;
+}
+
+static void mac_address_string(struct printf_info *info, u8 *addr,
+ bool separator)
+{
+ /* (6 * 2 hex digits), 5 colons and trailing zero */
+ char mac_addr[6 * 3];
+ char *p = mac_addr;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ p = pack_hex_byte(p, addr[i]);
+ if (separator && i != 5)
+ *p++ = ':';
+ }
+ *p = '\0';
+
+ string(info, mac_addr);
+}
+
+static char *put_dec_trunc(char *buf, unsigned int q)
+{
+ unsigned int 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;
+}
+
+static void ip4_addr_string(struct printf_info *info, u8 *addr)
+{
+ /* (4 * 3 decimal digits), 3 dots and trailing zero */
+ char ip4_addr[4 * 4];
+ char temp[3]; /* hold each IP quad in reverse order */
+ char *p = ip4_addr;
+ int i, digits;
+
+ for (i = 0; i < 4; i++) {
+ digits = put_dec_trunc(temp, addr[i]) - temp;
+ /* reverse the digits in the quad */
+ while (digits--)
+ *p++ = temp[digits];
+ if (i != 3)
+ *p++ = '.';
+ }
+ *p = '\0';
+
+ string(info, ip4_addr);
+}
+#endif
+
+/*
+ * Show a '%p' thing. A kernel extension is that the '%p' is followed
+ * by an extra set of characters that are extended format
+ * specifiers.
+ *
+ * Right now we handle:
+ *
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+ * usual colon-separated hex notation.
+ * - 'm' Same as above except there is no colon-separator.
+ * - 'I4'for IPv4 addresses printed in the usual way (dot-separated
+ * decimal).
+ */
+
+static void __maybe_unused pointer(struct printf_info *info, const char *fmt,
+ void *ptr)
+{
+#ifdef DEBUG
+ unsigned long num = (uintptr_t)ptr;
+ unsigned long div;
+#endif
+
+ switch (*fmt) {
+#ifdef DEBUG
+ case 'a':
+
+ switch (fmt[1]) {
+ case 'p':
+ default:
+ num = *(phys_addr_t *)ptr;
+ break;
+ }
+ break;
+#endif
+#ifdef CONFIG_SPL_NET_SUPPORT
+ case 'm':
+ return mac_address_string(info, ptr, false);
+ case 'M':
+ return mac_address_string(info, ptr, true);
+ case 'I':
+ if (fmt[1] == '4')
+ return ip4_addr_string(info, ptr);
+#endif
+ default:
+ break;
+ }
+#ifdef DEBUG
+ div = 1UL << (sizeof(long) * 8 - 4);
+ for (; div; div /= 0x10)
+ div_out(info, &num, div);
+#endif
+}
+
+static int _vprintf(struct printf_info *info, const char *fmt, va_list va)
+{
+ char ch;
+ char *p;
+ unsigned long num;
+ char buf[12];
+ unsigned long div;
+
+ while ((ch = *(fmt++))) {
+ if (ch != '%') {
+ info->putc(info, ch);
+ } else {
+ bool lz = false;
+ int width = 0;
+ bool islong = false;
+
+ ch = *(fmt++);
+ if (ch == '-')
+ ch = *(fmt++);
+
+ if (ch == '0') {
+ ch = *(fmt++);
+ lz = 1;
+ }
+
+ if (ch >= '0' && ch <= '9') {
+ width = 0;
+ while (ch >= '0' && ch <= '9') {
+ width = (width * 10) + ch - '0';
+ ch = *fmt++;
+ }
+ }
+ if (ch == 'l') {
+ ch = *(fmt++);
+ islong = true;
+ }
+
+ info->bf = buf;
+ p = info->bf;
+ info->zs = 0;
+
+ switch (ch) {
+ case '\0':
+ goto abort;
+ case 'u':
+ case 'd':
+ div = 1000000000;
+ if (islong) {
+ num = va_arg(va, unsigned long);
+ if (sizeof(long) > 4)
+ div *= div * 10;
+ } else {
+ num = va_arg(va, unsigned int);
+ }
+
+ if (ch == 'd') {
+ if (islong && (long)num < 0) {
+ num = -(long)num;
+ out(info, '-');
+ } else if (!islong && (int)num < 0) {
+ num = -(int)num;
+ out(info, '-');
+ }
+ }
+ if (!num) {
+ out_dgt(info, 0);
+ } else {
+ for (; div; div /= 10)
+ div_out(info, &num, div);
+ }
+ break;
+ case 'p':
+#ifdef DEBUG
+ pointer(info, fmt, va_arg(va, void *));
+ /*
+ * Skip this because it pulls in _ctype which is
+ * 256 bytes, and we don't generally implement
+ * pointer anyway
+ */
+ while (isalnum(fmt[0]))
+ fmt++;
+ break;
+#else
+ islong = true;
+ /* no break */
+#endif
+ case 'x':
+ if (islong) {
+ num = va_arg(va, unsigned long);
+ div = 1UL << (sizeof(long) * 8 - 4);
+ } else {
+ num = va_arg(va, unsigned int);
+ div = 0x10000000;
+ }
+ if (!num) {
+ out_dgt(info, 0);
+ } else {
+ for (; div; div /= 0x10)
+ div_out(info, &num, div);
+ }
+ break;
+ case 'c':
+ out(info, (char)(va_arg(va, int)));
+ break;
+ case 's':
+ p = va_arg(va, char*);
+ break;
+ case '%':
+ out(info, '%');
+ default:
+ break;
+ }
+
+ *info->bf = 0;
+ info->bf = p;
+ while (*info->bf++ && width > 0)
+ width--;
+ while (width-- > 0)
+ info->putc(info, lz ? '0' : ' ');
+ if (p) {
+ while ((ch = *p++))
+ info->putc(info, ch);
+ }
+ }
+ }
+
+abort:
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(PRINTF)
+static void putc_normal(struct printf_info *info, char ch)
+{
+ putc(ch);
+}
+
+int vprintf(const char *fmt, va_list va)
+{
+ struct printf_info info;
+
+ info.putc = putc_normal;
+ return _vprintf(&info, fmt, va);
+}
+
+int printf(const char *fmt, ...)
+{
+ struct printf_info info;
+
+ va_list va;
+ int ret;
+
+ info.putc = putc_normal;
+ va_start(va, fmt);
+ ret = _vprintf(&info, fmt, va);
+ va_end(va);
+
+ return ret;
+}
+#endif
+
+static void putc_outstr(struct printf_info *info, char ch)
+{
+ *info->outstr++ = ch;
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+ struct printf_info info;
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+ info.outstr = buf;
+ info.putc = putc_outstr;
+ ret = _vprintf(&info, fmt, va);
+ va_end(va);
+ *info.outstr = '\0';
+
+ return ret;
+}
+
+#if CONFIG_IS_ENABLED(LOG)
+/* Note that size is ignored */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list va)
+{
+ struct printf_info info;
+ int ret;
+
+ info.outstr = buf;
+ info.putc = putc_outstr;
+ ret = _vprintf(&info, fmt, va);
+ *info.outstr = '\0';
+
+ return ret;
+}
+#endif
+
+/* Note that size is ignored */
+int snprintf(char *buf, size_t size, const char *fmt, ...)
+{
+ struct printf_info info;
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+ info.outstr = buf;
+ info.putc = putc_outstr;
+ ret = _vprintf(&info, fmt, va);
+ va_end(va);
+ *info.outstr = '\0';
+
+ return ret;
+}
+
+void print_grouped_ull(unsigned long long int_val, int digits)
+{
+ /* Don't try to print the upper 32-bits */
+ printf("%ld ", (ulong)int_val);
+}
diff --git a/lib/tizen/Makefile b/lib/tizen/Makefile
new file mode 100644
index 00000000..3651ea21
--- /dev/null
+++ b/lib/tizen/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2012 Samsung Electronics
+# Donghwa Lee <dh09.lee@samsung.com>
+
+obj-$(CONFIG_TIZEN) += tizen.o
diff --git a/lib/tizen/tizen.c b/lib/tizen/tizen.c
new file mode 100644
index 00000000..916b2597
--- /dev/null
+++ b/lib/tizen/tizen.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012 Samsung Electronics
+ * Donghwa Lee <dh09.lee@samsung.com>
+ */
+
+#include <common.h>
+#include <lcd.h>
+#include <libtizen.h>
+
+#include "tizen_logo_16bpp.h"
+#include "tizen_logo_16bpp_gzip.h"
+
+#ifdef CONFIG_LCD
+void get_tizen_logo_info(vidinfo_t *vid)
+{
+ switch (vid->vl_bpix) {
+ case 4:
+ vid->logo_width = TIZEN_LOGO_16BPP_WIDTH;
+ vid->logo_height = TIZEN_LOGO_16BPP_HEIGHT;
+ vid->logo_x_offset = TIZEN_LOGO_16BPP_X_OFFSET;
+ vid->logo_y_offset = TIZEN_LOGO_16BPP_Y_OFFSET;
+#if defined(CONFIG_VIDEO_BMP_GZIP)
+ vid->logo_addr = (ulong)tizen_logo_16bpp_gzip;
+#else
+ vid->logo_addr = (ulong)tizen_logo_16bpp;
+#endif
+ break;
+ default:
+ vid->logo_addr = 0;
+ break;
+ }
+}
+#endif
diff --git a/lib/tizen/tizen_logo_16bpp.h b/lib/tizen/tizen_logo_16bpp.h
new file mode 100644
index 00000000..12e86269
--- /dev/null
+++ b/lib/tizen/tizen_logo_16bpp.h
@@ -0,0 +1,7934 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#ifndef __TIZEN_LOGO_16BPP__
+#define __TIZEN_LOGO_16BPP__
+
+#define TIZEN_LOGO_16BPP_WIDTH 452
+#define TIZEN_LOGO_16BPP_HEIGHT 140
+
+/* Center align offsets for word "TIZEN" */
+#define TIZEN_LOGO_16BPP_X_OFFSET (16)
+#define TIZEN_LOGO_16BPP_Y_OFFSET (-20)
+
+/* Format: BMP RGB565 16BPP 452x140 */
+unsigned char tizen_logo_16bpp[] = {
+0x42,0x4d,0xa6,0xee,0x01,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x38,0x00,
+0x00,0x00,0xc4,0x01,0x00,0x00,0x8c,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x03,0x00,
+0x00,0x00,0x60,0xee,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0xe0,0x07,0x00,0x00,0x1f,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x21,0x08,0x86,0x31,0x65,0x29,0x41,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,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x20,0x00,0x20,0x08,0x20,0x00,
+0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x08,0x20,0x00,0x20,0x00,0x20,0x00,
+0x20,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,0xaa,0x52,0x34,0xa5,0xb6,0xb5,
+0x96,0xb5,0x34,0xa5,0xd2,0x94,0xef,0x7b,0xeb,0x5a,0x08,0x42,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,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,0x61,0x08,
+0x6e,0x6b,0x71,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x71,0x8c,0x51,0x8c,0x71,0x8c,
+0x71,0x8c,0x71,0x8c,0x51,0x8c,0x51,0x8c,0x71,0x8c,0x51,0x8c,0x51,0x8c,0x71,0x8c,
+0x71,0x8c,0x51,0x8c,0x8a,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,
+0x10,0x84,0xb2,0x94,0xb2,0x94,0xd2,0x94,0xb2,0x94,0xd2,0x94,0xb2,0x94,0xb2,0x94,
+0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xd2,0x94,
+0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xd2,0x94,0xb2,0x94,
+0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xd2,0x94,0xd2,0x94,
+0xb2,0x94,0xd2,0x94,0xb2,0x94,0xd2,0x94,0xb2,0x94,0xd2,0x94,0xd2,0x9c,0xd2,0x94,
+0xb2,0x94,0xd2,0x94,0xb2,0x9c,0xd2,0x94,0xd2,0x94,0xd2,0x94,0xb3,0x94,0xd2,0x94,
+0xb3,0x94,0xd2,0x94,0xb3,0x94,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0x92,0x94,0x08,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0x18,0x30,0x84,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,
+0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,
+0x14,0xa5,0x14,0x9d,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0x9d,
+0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0x9d,
+0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x34,0xa5,
+0x30,0x84,0x62,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,0x21,0x08,0x10,0x84,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x30,0x8c,0x62,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,
+0xe7,0x39,0x14,0xa5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x75,0xad,0x13,0x9d,0x72,0x94,0x8e,0x73,0x8a,0x52,0xa6,0x31,
+0xa2,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x42,0xb2,0x94,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0x14,0xa5,0x14,0xa5,0xf3,0x9c,
+0x2c,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x94,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xab,0x5a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xef,0x7b,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0xc7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd3,0x9c,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x51,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x30,0x84,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xf7,0xbd,0x51,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0x92,0x94,0x14,0xa5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0x55,0xa5,0xd3,0x9c,0x30,0x84,0x2c,0x63,
+0x28,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xc3,0x18,0x55,0xad,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x8a,0x52,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd7,0xb5,0xf7,0xbd,0xae,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,0x96,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xb6,0xb5,0xd7,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd7,0xbd,0x54,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xd7,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0x55,0xad,0x62,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,0x10,0x84,
+0xf3,0x9c,0xf3,0x9c,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0x91,0x94,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0xd6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x08,0x54,0xad,0xd6,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,0xb6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xb6,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xb6,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0x54,0xad,0x41,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,
+0x21,0x00,0x34,0xa5,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,0x4d,0x6b,0x14,0xa5,0xd3,0x9c,0xf3,0x9c,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd7,0xbd,0xae,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x6b,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xbd,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb7,0xb5,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0x55,0xad,0xa2,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,0x20,0x00,0x34,0xa5,0xd7,0xbd,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xb5,0x55,0xad,0x82,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,0x69,0x4a,0x14,0xa5,0xf3,0x9c,
+0xd2,0x94,0xd3,0x9c,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0xb6,0xb5,0x30,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,
+0x55,0xad,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,
+0x20,0x00,0x34,0xa5,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xb5,0x55,0xad,0xa2,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,
+0x45,0x29,0xf3,0x9c,0x13,0x9d,0xd3,0x9c,0xd2,0x94,0xd3,0x9c,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x6b,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xbd,0xb6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd7,0xb5,
+0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0x55,0xad,0x82,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,0x20,0x00,0x34,0xa5,0xd7,0xbd,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xbd,0x55,0xad,0x82,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,0x71,0x8c,0x34,0xa5,0xf3,0x9c,0xd3,0x9c,
+0xb2,0x94,0xd2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x08,0x55,0xad,
+0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,0xb6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0x55,0xad,0xa2,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,
+0x20,0x00,0x34,0xa5,0xd7,0xbd,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0xcf,0x7b,
+0x55,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0xd2,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x8e,0x73,0xf7,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd7,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,
+0xd7,0xbd,0x55,0xad,0x82,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,0x20,0x00,0x34,0xa5,0xd7,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xbd,0x55,0xad,0x82,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,0xeb,0x5a,0x54,0xad,0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd3,0x9c,
+0xb2,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xf3,0x9c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x4a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,
+0xd6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x10,0x75,0xad,0xd7,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd7,0xb5,0xd7,0xb5,
+0xd6,0xbd,0xb7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,
+0x20,0x00,0x34,0xa5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0x55,0xad,0x82,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,0xc7,0x39,0x34,0xa5,0x54,0xa5,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8a,0x52,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xef,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x8e,0x73,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xb5,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd7,0xbd,0x75,0xad,0xa2,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,0x20,0x00,0x54,0xa5,0xd7,0xbd,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb7,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0x55,0xad,0x82,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,
+0x82,0x10,0xf3,0x9c,0x55,0xad,0x34,0xa5,0x14,0xa5,0x13,0x9d,0xf3,0x9c,0xd3,0x94,
+0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xf3,0x9c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,
+0xd6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x10,0x75,0xad,0xd7,0xbd,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x75,0xad,0xa2,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,
+0x20,0x00,0x34,0xa5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,0x51,0x8c,0x75,0xad,0x55,0xad,0x34,0xa5,
+0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd2,0x9c,0xb2,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0x13,0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xab,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0x0f,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xae,0x73,0xf7,0xbd,0xb7,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0x75,0xad,0x82,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,0x20,0x08,0x34,0xa5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xbd,0xb6,0xb5,0xd7,0xb5,0xb6,0xb5,
+0xd7,0xbd,0x75,0xad,0xc3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x6b,
+0x96,0xb5,0x55,0xad,0x55,0xa5,0x34,0xa5,0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd2,0x94,
+0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xf3,0x9c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0x75,0xad,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x75,0xad,0xa2,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,
+0x20,0x00,0x54,0xa5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd7,0xbd,0x76,0xad,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x69,0x4a,0x76,0xad,0x75,0xad,0x55,0xad,0x54,0xad,0x34,0xa5,
+0x14,0xa5,0xf3,0x9c,0xf3,0x9c,0xb2,0x94,0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd7,0xbd,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xab,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xd6,0xb5,0x0f,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xae,0x73,
+0xf7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0x75,0xad,0x82,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,0x21,0x00,0x54,0xa5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0x75,0xad,0xe4,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,0x04,0x21,0x34,0xa5,0x96,0xad,
+0x75,0xad,0x55,0xad,0x35,0xad,0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,
+0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x14,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x52,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc3,0x18,0x75,0xad,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xef,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x75,0xad,0xa3,0x18,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x20,0x00,0x34,0xad,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xb2,0x94,0xb6,0xb5,0x76,0xad,0x75,0xad,0x55,0xad,0x54,0xad,0x34,0xa5,
+0x34,0xa5,0xf3,0x9c,0xf3,0x9c,0xd2,0x94,0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x34,0xa5,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,
+0xab,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,
+0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x10,0x7c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x31,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x73,0xf7,0xbd,
+0xb7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0x17,0xbe,0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x54,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x54,0xa5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0x75,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x7b,0xb6,0xb5,0x96,0xb5,0x75,0xad,
+0x75,0xad,0x55,0xad,0x54,0xad,0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xd2,0x94,
+0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0x34,0xa5,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,0xab,0x5a,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xf0,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xf7,0xbd,0xd2,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd2,0x9c,0xf7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x14,0x9d,0x62,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,0x66,0x29,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xb6,0xb5,0xab,0x5a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x5a,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,
+0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0x92,0x94,0x92,0x94,0x96,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xbd,0x34,0xa5,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,
+0xab,0x5a,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x83,0xf7,0xbd,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x76,0xb5,0x96,0xb5,
+0xf3,0x9c,0x2c,0x63,0x2c,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,
+0x2d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,
+0x4d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,
+0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x2d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,
+0x2d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x4d,0x6b,0x0c,0x63,
+0x8a,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xb6,0xb5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x75,0xad,0x0c,0x63,0xcb,0x5a,0xeb,0x5a,0xeb,0x5a,0xeb,0x5a,0xeb,0x5a,
+0xeb,0x5a,0xeb,0x5a,0xeb,0x5a,0xeb,0x5a,0xcb,0x5a,0xeb,0x5a,0xaa,0x52,0x6a,0x4a,
+0x8a,0x52,0x69,0x52,0x8a,0x4a,0x8a,0x52,0x6a,0x4a,0x8a,0x52,0x8a,0x52,0x8a,0x52,
+0x8a,0x52,0x6a,0x52,0x89,0x4a,0x8a,0x52,0x8a,0x52,0x6a,0x4a,0x8a,0x52,0x89,0x52,
+0x6a,0x52,0x6a,0x52,0x8a,0x52,0x6a,0x52,0x89,0x52,0x89,0x4a,0x8a,0x52,0x89,0x4a,
+0x8a,0x4a,0x8a,0x52,0x8a,0x52,0x89,0x52,0x8a,0x4a,0x8a,0x4a,0x8a,0x52,0x69,0x4a,
+0x24,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,
+0xd7,0xbd,0x95,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0x95,0xad,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,
+0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,0x34,0xa5,0x13,0x9d,0xd3,0x9c,0xb2,0x94,
+0x92,0x94,0x92,0x94,0x96,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x34,0xa5,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,0xcb,0x52,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x39,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x94,0xd6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x76,0xb5,0x76,0xad,0x95,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x8a,0x52,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x45,0x29,0xb6,0xb5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0x14,0xa5,0xd7,0xbd,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x76,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,
+0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xb2,0x94,0xb2,0x94,0x92,0x94,0x96,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb7,0xbd,0x34,0xa5,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,
+0xab,0x5a,0xd6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,
+0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x31,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xbd,0xb6,0xb5,0xd7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,
+0xf3,0x9c,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x75,0xad,0x95,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x49,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd7,0xb5,
+0xd7,0xbd,0x96,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x51,0x8c,0xd7,0xbd,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x95,0xb5,
+0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,0x14,0xa5,0x13,0x9d,0xd3,0x9c,0xd2,0x94,
+0x92,0x94,0x92,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0x34,0xa5,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,0xcb,0x5a,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xf7,0xbd,0xd2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x18,0x34,0xa5,0xb6,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x95,0xb5,0x96,0xb5,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x75,0xad,0x54,0xa5,0xc7,0x39,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x6b,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,
+0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd3,0x9c,0x92,0x94,0x92,0x94,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xbd,0x34,0xa5,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,
+0xab,0x5a,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,
+0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x39,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x86,0x29,0x55,0xad,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xad,
+0x76,0xb5,0x95,0xb5,0x76,0xb5,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x55,0xad,0x75,0xad,
+0x55,0xad,0x55,0xad,0x75,0xad,0x14,0xa5,0x45,0x29,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xad,
+0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,0x14,0xa5,0x13,0x9d,0xd3,0x9c,0xd2,0x94,
+0x92,0x94,0xb2,0x94,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0x34,0xa5,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,0xcb,0x5a,0xd6,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x75,0xad,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xb5,0x75,0xb5,
+0x95,0xad,0x75,0xb5,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x76,0xad,
+0xf3,0x9c,0xa2,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,0x04,0x21,0x96,0xb5,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc3,0x18,0x55,0xad,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x76,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,
+0x34,0xa5,0x14,0x9d,0xf3,0x9c,0xb2,0x9c,0x92,0x94,0x92,0x94,0x96,0xb5,0xd7,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xbd,0x34,0xa5,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,
+0xab,0x5a,0xd6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x31,0xd6,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd7,0xb5,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x52,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x76,0xb5,0x95,0xb5,0x96,0xad,0x76,0xad,0x76,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x92,0x94,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x94,0xf7,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xb5,
+0x75,0xad,0x75,0xad,0x55,0xad,0x54,0xa5,0x34,0xa5,0x13,0x9d,0xd3,0x9c,0xd2,0x94,
+0x92,0x94,0x92,0x94,0x96,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,0x34,0xa5,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,0xcb,0x5a,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0c,0x63,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x95,0xb5,0x96,0xb5,0x96,0xad,0x75,0xb5,0x76,0xad,0x96,0xb5,
+0x75,0xad,0x75,0xb5,0x95,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x96,0xb5,0x51,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0xb6,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xcf,0x7b,0xf7,0xbd,0xb7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x54,0xa5,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x94,0x92,0x94,0x92,0x94,0x96,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd7,0xbd,0x34,0xa5,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,
+0xab,0x5a,0xd6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x39,0xd6,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xb7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xf7,0xbd,0xd3,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x6b,0xb6,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xad,0x96,0xb5,0x96,0xb5,0x76,0xad,0x95,0xb5,0x75,0xb5,0x75,0xb5,
+0x96,0xb5,0x95,0xb5,0x75,0xad,0x75,0xad,0x75,0xb5,0x75,0xad,0x96,0xb5,0xcf,0x7b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x52,0xd7,0xb5,0xd7,0xbd,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xad,
+0x75,0xad,0x55,0xad,0x55,0xad,0x34,0xa5,0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd2,0x94,
+0x92,0x94,0x92,0x94,0x96,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x34,0xa5,0x41,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x5a,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0xd7,0xbd,0xd6,0xbd,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xef,0x7b,0xd6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,
+0x95,0xad,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x54,0xa5,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0x92,0x94,0xb2,0x94,0x96,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xab,0x5a,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0x39,0xd7,0xbd,
+0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xf7,0xbd,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8c,
+0xd7,0xbd,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0xab,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x95,0xb5,
+0x75,0xad,0x75,0xad,0x55,0xad,0x34,0xa5,0x34,0xa5,0x13,0x9d,0xf3,0x9c,0xd3,0x9c,
+0xb2,0x94,0xb2,0x94,0x96,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x5a,0xb6,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x94,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0x28,0x42,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x84,0xf7,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x54,0xad,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0xb2,0x94,0x96,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xcb,0x5a,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x41,0xf7,0xbd,
+0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd6,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x41,0x08,0x13,0x9d,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x75,0xad,0xa7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xec,0x62,0xd7,0xbd,0xb6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xad,
+0x75,0xad,0x75,0xad,0x55,0xad,0x34,0xa5,0x34,0xa5,0x13,0xa5,0xf3,0x9c,0xd3,0x9c,
+0x92,0x94,0x92,0x94,0x96,0xb5,0xd6,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x5a,0xb7,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x54,0xa5,0xd7,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0x55,0xad,
+0x25,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0x96,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0x39,0x96,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x75,0xad,0x55,0xad,0x55,0xad,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0x92,0x94,0x96,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xcb,0x5a,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x41,0xf7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0x75,0xad,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x14,0xa5,0x62,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,0x04,0x21,0xb6,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,
+0x14,0xa5,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x75,0xad,0x75,0xad,0x55,0xad,0x54,0xa5,0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd2,0x94,
+0xb2,0x94,0x91,0x8c,0x76,0xad,0xd6,0xbd,0xd6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd7,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0x55,0xad,0xa2,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x5a,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x4a,
+0xb6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xb5,
+0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0xb6,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8c,0xd7,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x75,0xad,0x75,0xad,0x55,0xad,0x54,0xa5,
+0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xd3,0x9c,0xb2,0x94,0xab,0x5a,0x34,0xa5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xeb,0x5a,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x41,0xf7,0xbd,
+0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x5a,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x51,0x8c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x95,0xb5,0x4d,0x6b,0x0c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,
+0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,
+0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,
+0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,0x2c,0x63,
+0x2c,0x63,0x2c,0x63,0x2c,0x63,0x6d,0x6b,0x6e,0x73,0x8e,0x73,0x4d,0x6b,0xe7,0x39,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x6b,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x75,0xad,0x75,0xad,0x55,0xad,0x54,0xa5,0x34,0xa5,0x14,0xa5,0xf3,0x9c,0xf3,0x9c,
+0x2d,0x6b,0x00,0x00,0x34,0xa5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x2d,0x6b,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xef,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0xb6,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x18,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xbe,
+0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xbe,0x17,0xc6,0x18,0xc6,0x18,0xc6,
+0x17,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xbe,0x17,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0xf7,0xbd,0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x28,0x42,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x95,0xad,0x75,0xad,0x55,0xad,0x55,0xad,
+0x34,0xa5,0x14,0xa5,0x14,0x9d,0x30,0x84,0x00,0x00,0x00,0x00,0x54,0xa5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x7b,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0x55,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xa5,0xf7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0x34,0xa5,0xb6,0xb5,0x96,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xb7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x75,0xb5,0x75,0xad,0x55,0xad,0x54,0xad,0x34,0xa5,0x14,0xa5,0xd3,0x9c,0x45,0x29,
+0x00,0x00,0x21,0x00,0x54,0xa5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xb5,0x55,0xad,0xa2,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xaa,0x52,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x55,0xad,0x41,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,0x14,0xa5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x71,0x8c,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x95,0xb5,0x75,0xad,0x55,0xad,0x55,0xa5,
+0x34,0xa5,0x14,0xa5,0x8a,0x52,0x00,0x00,0x00,0x00,0x21,0x08,0x54,0xa5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd7,0xbd,0x55,0xad,0x82,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0c,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xcf,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x92,0x94,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd6,0xb5,0x28,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0x96,0xb5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x55,0xad,0x21,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,0x14,0x9d,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xb6,0xb5,0x65,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x6b,0x96,0xb5,0x95,0xad,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x76,0xb5,0x75,0xad,0x55,0xad,0x55,0xa5,0x55,0xad,0xae,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x20,0x00,0x54,0xa5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xb6,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd7,0xbd,0x55,0xad,0xa2,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xaf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x96,0xb5,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x55,0xad,0x21,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,0x14,0xa5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0x4a,0x75,0xad,
+0x75,0xad,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x75,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,
+0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x54,0xa5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xb7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0x75,0xad,0xe4,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,
+0x0c,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xaf,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x82,0x10,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x55,0xad,0xe4,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,0x04,0x21,0xb6,0xb5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x55,0xad,0x21,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,0x14,0xa5,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xb6,0xb5,0x66,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0x14,0xa5,0x75,0xad,0x75,0xad,0x96,0xad,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x76,0xb5,0x75,0xad,0x55,0xad,0x34,0xa5,0x66,0x31,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x20,0x08,0x35,0xa5,0xf7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,
+0xb7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0x76,0xad,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xaf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x17,0xbe,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0x75,0xad,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0x14,0xa5,0x41,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,0x04,0x21,0xb6,0xb5,0xf7,0xc5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x75,0xad,0x82,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,0x14,0xa5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x94,0x75,0xad,0x55,0xad,
+0x75,0xad,0x75,0xad,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x95,0xb5,0x75,0xad,0x75,0xad,0xcb,0x5a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x55,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0x95,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd6,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xae,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0x39,0x96,0xb5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb2,0x94,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0xb6,0xb5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x76,0xb5,0xa3,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,0x14,0xa5,0xf7,0xc5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd6,0xb5,0x66,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8e,0x73,0x55,0xad,0x55,0xad,0x55,0xad,0x75,0xad,0x95,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0x96,0xad,0x96,0xb5,0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x21,0x08,0x55,0xad,0xf7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0xaf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x4a,0xd6,0xb5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0x30,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0xf8,0xc5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xbe,0x96,0xb5,0xa3,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd6,0xb5,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x52,0x34,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,
+0x75,0xad,0x75,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0xd3,0x9c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0x95,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xae,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xeb,0x5a,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xae,0x73,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0x96,0xb5,0xa3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xa5,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0xf3,0x9c,
+0x34,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x95,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0x55,0xad,0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x14,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xaf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x4d,0x6b,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,0xb6,0xb5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x96,0xb5,0xa3,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x18,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0x86,0x31,0x00,0x00,
+0x00,0x00,0x20,0x00,0x71,0x8c,0x14,0xa5,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,
+0x75,0xad,0x76,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xeb,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xce,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x7b,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0x89,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0x96,0xb5,0xa3,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,0x14,0xa5,0xf7,0xc5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xc7,0x39,0x00,0x00,0x00,0x00,0x8e,0x73,0xf3,0x9c,0xf3,0x9c,
+0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xad,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xbd,0x10,0x84,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x14,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0x17,0xbe,0xd3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x84,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0xe8,0x41,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0x17,0xc6,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x96,0xb5,0xa3,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x17,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xa7,0x39,0x00,0x00,
+0xaa,0x52,0xd3,0x9c,0xf3,0x9c,0xf3,0xa4,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,
+0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xd7,0xbd,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x92,0x94,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0x75,0xad,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x17,0xbe,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0x96,0xb5,0xa3,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,0x14,0xa5,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x65,0x29,0x45,0x29,0x92,0x94,0xd2,0x9c,0xd3,0x9c,0x13,0x9d,
+0x14,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0x96,0xb5,0x86,0x31,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf3,0x9c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0xf7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xf7,0xbd,0x34,0xa5,
+0xa3,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,0x24,0x21,0xb6,0xb5,0x18,0xc6,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x96,0xb5,0xa3,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0x89,0x4a,0xef,0x83,
+0xb2,0x94,0xd2,0x94,0xf3,0x9c,0x13,0x9d,0x34,0xa5,0x34,0xa5,0x55,0xad,0x75,0xad,
+0x75,0xad,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xec,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa2,0x10,0x34,0xa5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xf7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xc6,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0x17,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xc5,0xf7,0xbd,0x18,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0x18,0xbe,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf8,0xc5,0x17,0xbe,
+0xf8,0xbd,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x18,0xc6,0x17,0xbe,0xf8,0xc5,0x17,0xbe,
+0xf8,0xc5,0x17,0xbe,0x17,0xc6,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0x18,0xbe,0x17,0xbe,0x17,0xc6,0xf7,0xbd,0xf8,0xbd,0xf7,0xbd,0xf7,0xbd,0x38,0xc6,
+0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xa5,0x17,0xc6,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x51,0x8c,0x71,0x8c,0x92,0x94,0xd2,0x94,0xf3,0x9c,0x13,0x9d,
+0x14,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x76,0xb5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x29,
+0x55,0xad,0xd7,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,0xb6,0xb5,0xd7,0xb5,
+0xf7,0xbd,0x71,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xc6,0x17,0xbe,0x17,0xc6,0xf7,0xbd,0xf8,0xbd,
+0x17,0xbe,0xf7,0xc5,0xf7,0xbd,0x18,0xbe,0x17,0xbe,0xf7,0xc5,0xf7,0xbd,0xf8,0xbd,
+0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x18,0xc6,
+0x17,0xbe,0xf8,0xbd,0x17,0xbe,0x18,0xc6,0x17,0xbe,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x55,0xad,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x18,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xb2,0x94,0x51,0x8c,
+0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x34,0xa5,0x55,0xad,0x75,0xad,
+0x75,0xad,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x14,0xa5,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x25,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf8,0xc5,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0x39,0x75,0xad,0xd7,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xf7,0xbd,0xef,0x7b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xc6,
+0x17,0xbe,0xf7,0xbd,0x18,0xbe,0x17,0xbe,0x17,0xc6,0xf7,0xbd,0x18,0xbe,0x17,0xbe,
+0x17,0xbe,0x17,0xbe,0x18,0xbe,0x17,0xbe,0xf7,0xc5,0xf7,0xbd,0xf8,0xbd,0x17,0xbe,
+0x18,0xc6,0x96,0xb5,0x28,0x42,0xa6,0x31,0xc7,0x39,0xa7,0x39,0xc7,0x39,0xc7,0x39,
+0xa6,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,
+0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,
+0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,
+0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x31,0x66,0x31,0x65,0x29,0x65,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xa5,0x18,0xc6,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xb2,0x94,0x71,0x8c,0x92,0x94,0xd3,0x9c,0xf3,0x9c,0x13,0xa5,
+0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x76,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0x96,0xb5,0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x6b,0xd7,0xbd,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xbe,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x4a,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xc6,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x18,0xc6,
+0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf8,0xbd,0x17,0xbe,0xf8,0xc5,
+0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x18,0xbe,0x18,0xc6,0x75,0xad,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xb2,0x94,0x71,0x8c,
+0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,
+0x95,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xec,0x62,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xbe,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x5a,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xaa,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xbe,
+0xf8,0xc5,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x18,0xbe,0x17,0xbe,
+0x17,0xc6,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf8,0xbd,0x17,0xbe,0xf7,0xc5,0x17,0xbe,
+0x18,0xc6,0x75,0xad,0x21,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,0x14,0xa5,0x18,0xc6,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xb2,0x94,0x71,0x8c,0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,
+0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x30,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xbe,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x63,0x96,0xb5,0x96,0xb5,0x76,0xb5,0x96,0xad,
+0x96,0xb5,0x95,0xb5,0x96,0xad,0x76,0xb5,0x96,0xad,0x76,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x96,0xb5,0x28,0x42,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xd6,0xb5,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x17,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x17,0xbe,0x17,0xbe,0x17,0xbe,0x18,0xbe,0x18,0xc6,0x75,0xad,0x41,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,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd2,0x94,0x71,0x8c,
+0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,
+0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x14,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0xd7,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xc6,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8e,0x73,0x95,0xb5,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x76,0xad,0x75,0xad,0x76,0xad,0x95,0xad,0x76,0xb5,0x95,0xad,
+0x96,0xb5,0x55,0xad,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xb6,0xb5,0x18,0xc6,
+0xf8,0xc5,0x17,0xbe,0x18,0xc6,0x17,0xc6,0xf8,0xc5,0x18,0xbe,0x17,0xbe,0x17,0xc6,
+0xf7,0xbd,0x18,0xbe,0x18,0xc6,0x17,0xbe,0xf8,0xbd,0x17,0xbe,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x75,0xad,0x21,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,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xb2,0x94,0x71,0x8c,0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,
+0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xb6,0xb5,
+0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x63,0xd7,0xbd,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x7b,0x75,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x75,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x14,0xa5,0x04,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xd6,0xb5,0x18,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xbe,0x17,0xbe,
+0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x17,0xc6,0x18,0xbe,0x17,0xc6,
+0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,0x75,0xad,0x41,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,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd2,0x94,0x71,0x8c,
+0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,
+0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xeb,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x4d,0x6b,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb6,0xbd,0xd7,0xb5,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x84,0x55,0xad,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x34,0xa5,0x54,0xa5,0x34,0xa5,0x54,0xa5,0x54,0xa5,0x54,0xa5,
+0x35,0xad,0x54,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,
+0x75,0xad,0x75,0xad,0x96,0xb5,0xd2,0x94,0x41,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,0x24,0x21,0xb6,0xb5,0x18,0xc6,
+0x18,0xc6,0x18,0xbe,0x17,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x75,0xad,0x21,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,0xf3,0x9c,0x18,0xc6,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd3,0x9c,0x71,0x8c,0xb2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,
+0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x17,0xc6,0x10,0x84,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x13,0x9d,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x65,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x73,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0xf8,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xc6,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8c,
+0x34,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,
+0x34,0xa5,0x14,0xa5,0x34,0xa5,0x14,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x54,0xa5,0x54,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x76,0xb5,
+0x71,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xd6,0xb5,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x41,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,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xd2,0x9c,0x71,0x94,
+0xd2,0x94,0xd3,0x9c,0x13,0x9d,0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x76,0xad,
+0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0x17,0xbe,0x14,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xb6,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8e,0x73,0xf7,0xbd,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x08,0x71,0x8c,0x14,0xa5,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0x13,0x9d,0xf3,0xa4,0x13,0x9d,0xf3,0x9c,0x13,0x9d,
+0x14,0xa5,0x14,0x9d,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x34,0xa5,0x14,0xa5,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x34,0xa5,0x54,0xa5,0x75,0xad,0xef,0x7b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x21,0xd6,0xb5,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xbe,
+0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xbe,
+0x18,0xc6,0x75,0xad,0x41,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,0xf3,0x9c,0x18,0xc6,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd3,0x9c,0x91,0x8c,0xb2,0x94,0xf3,0x9c,0xf3,0x9c,0x14,0xa5,
+0x34,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb7,0xbd,0xd6,0xbd,0xd7,0xbd,0xf7,0xbd,0xb6,0xb5,0x66,0x31,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0x96,0xb5,0x65,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x73,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xe3,0x18,0x72,0x94,0xf3,0x9c,0xd3,0x9c,0xd3,0x9c,0xd3,0x9c,0xd3,0x9c,0xd3,0x9c,
+0xf3,0x9c,0xd3,0x9c,0xf3,0x9c,0xd3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0x13,0x9d,0x14,0xa5,0x14,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x54,0xa5,0x55,0xad,0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x24,0x21,0xd6,0xb5,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x41,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,0xf3,0x9c,0x38,0xc6,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xd3,0x9c,0x92,0x94,
+0xd2,0x94,0xf3,0x9c,0x13,0x9d,0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xeb,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0x96,0xb5,0x45,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8e,0x73,0xf7,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,0x72,0x94,0xb2,0x94,
+0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,
+0xb2,0x94,0xb2,0x94,0xb3,0x94,0xd2,0x9c,0xd3,0x9c,0xd3,0x9c,0xd3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xf3,0x9c,0x14,0xa5,0x14,0xa5,0x34,0xa5,0x34,0xa5,0x55,0xad,0xcb,0x5a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x21,0xb6,0xb5,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,
+0x18,0xc6,0x75,0xad,0x21,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,0xf3,0x9c,0x18,0xc6,0x17,0xbe,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xd3,0x9c,0x92,0x94,0xb3,0x94,0xf3,0x9c,0x14,0xa5,0x34,0xa5,
+0x54,0xa5,0x55,0xad,0x75,0xad,0x96,0xad,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xd7,0xb5,0xd6,0xbd,0xf7,0xbd,0xef,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0x96,0xb5,0x45,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x73,0xf7,0xbd,0xd6,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa6,0x31,0x71,0x8c,0x92,0x94,0x71,0x94,0x71,0x8c,0x72,0x94,
+0x91,0x8c,0x92,0x94,0x92,0x94,0x92,0x94,0x92,0x94,0x92,0x94,0x92,0x94,0x92,0x94,
+0xb2,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x9c,0xd3,0x9c,0xd3,0x9c,0xf3,0x9c,0xf3,0x9c,
+0x13,0x9d,0x14,0xa5,0x34,0xa5,0x34,0xa5,0x28,0x42,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa3,0x18,0xb6,0xb5,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x76,0xb5,0x41,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,0x13,0x9d,0x38,0xc6,0x18,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x18,0xc6,0xf3,0x9c,0x92,0x94,
+0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x96,0xb5,
+0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xf7,0xbd,0x13,0x9d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd6,0xb5,0xd7,0xb5,0x96,0xb5,0x65,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8e,0x73,0xf7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe7,0x39,
+0x51,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x51,0x8c,
+0x51,0x8c,0x51,0x8c,0x71,0x8c,0x71,0x8c,0x71,0x8c,0x92,0x94,0x92,0x94,0x92,0x94,
+0x92,0x94,0xb2,0x94,0xd2,0x94,0xd2,0x9c,0xd3,0x9c,0xf3,0x9c,0xf3,0x9c,0x14,0xa5,
+0x14,0xa5,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x38,0xc6,0x75,0xad,0x41,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,0x13,0x9d,0x18,0xc6,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0x18,0xbe,0xf3,0x9c,0x92,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,
+0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd7,0xbd,0x96,0xb5,0x45,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x73,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x41,0x10,0x84,0x10,0x84,0x10,0x84,
+0x10,0x84,0x10,0x84,0x10,0x84,0x10,0x84,0x10,0x84,0x10,0x84,0x30,0x84,0x30,0x84,
+0x30,0x84,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x71,0x8c,0x71,0x8c,0x92,0x94,0x92,0x94,
+0xb2,0x94,0xd2,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0xd3,0x9c,0x24,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa3,0x18,0xb6,0xb5,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xf3,0x9c,0x38,0xc6,0x18,0xc6,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x18,0xc6,
+0x17,0xbe,0x17,0xc6,0x17,0xbe,0xf7,0xc5,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x17,0xc6,0xf3,0x9c,0x92,0x94,
+0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xb5,
+0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xd7,0xbd,0xd7,0xbd,0xcb,0x5a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x6d,0x6b,0xf7,0xbd,0xb7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0x6d,0x6b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x45,0x29,0x66,0x31,0x65,0x29,0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,
+0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,
+0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,0x65,0x31,0x65,0x29,0x66,0x31,0x65,0x29,
+0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,
+0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,0x65,0x29,0x65,0x29,0x66,0x31,0x65,0x29,
+0x45,0x29,0x8d,0x6b,0x51,0x8c,0x51,0x8c,0x51,0x8c,0x71,0x8c,0x72,0x8c,0x71,0x8c,
+0x72,0x94,0x92,0x94,0x92,0x94,0x92,0x94,0x92,0x94,0xb2,0x94,0xb2,0x94,0xb2,0x94,
+0xb2,0x94,0xd2,0x9c,0xd3,0x9c,0xf3,0x9c,0xf3,0x9c,0x13,0x9d,0x14,0xa5,0x34,0xa5,
+0x34,0xa5,0x75,0xad,0xd3,0x9c,0xc3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0xb6,0xb5,0x69,0x4a,0xe7,0x39,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,
+0x45,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x9d,0x18,0xc6,0x17,0xbe,
+0xf8,0xc5,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0x18,0xc6,0xf3,0x9c,0x92,0x94,0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,
+0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0xb6,0xb5,0xf7,0xbd,
+0xcf,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x31,0x08,0x42,0xe8,0x41,0xe8,0x41,
+0xe8,0x41,0xe8,0x41,0xe8,0x41,0xe8,0x41,0x08,0x42,0xe8,0x41,0x08,0x42,0xe8,0x41,
+0x08,0x42,0xe8,0x41,0x08,0x42,0xe8,0x41,0x08,0x42,0x08,0x42,0x08,0x42,0xe8,0x41,
+0x08,0x42,0x08,0x42,0x08,0x42,0xc7,0x39,0x30,0x84,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0x51,0x8c,0x29,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,
+0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,
+0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,0x69,0x4a,
+0x49,0x4a,0xc3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,0x14,0xa5,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x2c,0x63,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0xf7,0xbd,0x2c,0x63,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x9d,0x38,0xc6,0x17,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xbe,0xf8,0xbd,
+0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf8,0xbd,0xf7,0xbd,0xf8,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xf3,0x9c,0xb2,0x94,
+0xd3,0x9c,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,
+0x96,0xb5,0xb6,0xb5,0xd7,0xbd,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x92,0x94,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x18,0xc6,0x96,0xb5,0xe7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0x9c,
+0x38,0xc6,0x18,0xc6,0x18,0xbe,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x38,0xc6,0x8a,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xbe,
+0x38,0xc6,0xd7,0xb5,0xe3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x9d,0x38,0xc6,0x17,0xc6,
+0x18,0xbe,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0x18,0xc6,0x17,0xbe,0x18,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0x18,0xc6,0xf3,0x9c,0xb2,0x94,0xf3,0x9c,0x13,0x9d,0x34,0xa5,0x54,0xa5,
+0x55,0xad,0x75,0xad,0x76,0xb5,0x96,0xb5,0x96,0xb5,0xb6,0xb5,0x75,0xad,0x45,0x29,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x6d,0x6b,0xf7,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xbd,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0xd3,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x18,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x21,0x00,0x75,0xad,0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,
+0x17,0xc6,0xf8,0xbd,0x18,0xbe,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x17,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0xa7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xf4,0x9c,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,
+0x18,0xc6,0xf8,0xbd,0x18,0xbe,0x18,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf8,0xc5,
+0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x18,0xc6,0x13,0x9d,0xb2,0x94,
+0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,0x75,0xad,0x96,0xad,0x96,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xaa,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0xa5,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x14,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x75,0xad,
+0x18,0xc6,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf8,0xc5,0x17,0xbe,
+0xf8,0xbd,0x17,0xbe,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,
+0x18,0xbe,0x17,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x38,0xc6,0x2c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x9d,0x38,0xc6,0x18,0xbe,
+0x17,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xbe,0x17,0xbe,0xf7,0xc5,0x17,0xbe,
+0xf7,0xc5,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0xf8,0xc5,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0xf7,0xbd,0x18,0xc6,0x14,0xa5,0xd2,0x94,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xa5,
+0x55,0xad,0x75,0xad,0x96,0xb5,0x96,0xb5,0xd6,0xb5,0xaf,0x73,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xf3,0xa4,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x86,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x14,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x18,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x75,0xad,0x18,0xc6,0x17,0xbe,0x17,0xbe,0x18,0xc6,
+0x18,0xbe,0x17,0xc6,0x17,0xc6,0x18,0xc6,0x17,0xc6,0x17,0xbe,0x18,0xbe,0x18,0xc6,
+0x17,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x55,0xad,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0xa7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x13,0xa5,0x38,0xc6,0x18,0xc6,0x17,0xbe,0x17,0xc6,0x18,0xbe,0x18,0xbe,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xbe,
+0x18,0xbe,0xf8,0xbd,0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x18,0xc6,0x14,0xa5,0xd3,0x9c,
+0x13,0x9d,0x14,0xa5,0x34,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x96,0xb5,0xb6,0xb5,
+0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xb7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x34,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x17,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0x17,0xbe,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x75,0xad,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,
+0x18,0xbe,0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x38,0xc6,0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x9d,0x38,0xc6,0x18,0xbe,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,
+0xf8,0xbd,0x17,0xbe,0x17,0xc6,0x17,0xc6,0xf8,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,
+0xf8,0xc5,0x18,0xbe,0x14,0xa5,0xd3,0x9c,0x13,0x9d,0x34,0xa5,0x34,0xa5,0x55,0xad,
+0x75,0xad,0x75,0xad,0x96,0xb5,0x55,0xad,0x04,0x21,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xf3,0x9c,0x17,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,0x86,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0x14,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x38,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x75,0xad,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0xa7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xa5,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xbe,0x18,0xc6,0x34,0xa5,0xd3,0x9c,
+0x14,0xa5,0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,0x95,0xb5,0x96,0xb5,0x8a,0x52,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xb7,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0x96,0xb5,0x96,0xb5,0x75,0xad,0x86,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xb7,0xbd,0xd7,0xb5,
+0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x34,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xf7,0xbd,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x75,0xad,
+0x18,0xc6,0x18,0xbe,0x17,0xbe,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,
+0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0x9c,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x17,0xbe,0x17,0xc6,0x17,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xc6,0x17,0xbe,0xf8,0xc5,0x18,0xbe,
+0x17,0xbe,0x18,0xc6,0x34,0xa5,0xf3,0x9c,0x14,0xa5,0x34,0xa5,0x55,0xad,0x55,0xad,
+0x75,0xad,0xb6,0xb5,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xad,0x75,0xad,0x86,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xc5,0x14,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0x38,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x75,0xad,0x38,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x75,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xb2,0x94,0x38,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x17,0xbe,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,
+0x18,0xbe,0x17,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x54,0xa5,0xf3,0x9c,
+0x34,0xa5,0x54,0xa5,0x55,0xad,0x55,0xad,0x96,0xb5,0x92,0x94,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,
+0x95,0xb5,0x75,0xad,0x75,0xad,0x66,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x14,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,
+0xf7,0xbd,0x17,0xbe,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x75,0xad,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0xeb,0x5a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x94,0x38,0xc6,0x17,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xbe,
+0x18,0xbe,0x18,0xc6,0x54,0xad,0x13,0xa5,0x34,0xa5,0x54,0xa5,0x55,0xad,0x75,0xad,
+0x34,0xa5,0xe4,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,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x76,0xb5,0x75,0xad,0x75,0xad,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xb6,0xb5,0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,0xd6,0xb5,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xc6,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xc5,0x17,0xbe,0xf7,0xc5,0x38,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x75,0xad,0x38,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,
+0x17,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x38,0xc6,0x55,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0xa7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xb3,0x9c,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x54,0xad,0x14,0xa5,
+0x34,0xa5,0x55,0xad,0x75,0xad,0x75,0xad,0x49,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xd7,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x96,0xb5,
+0x75,0xad,0x75,0xad,0x75,0xad,0xa7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,
+0xd6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,
+0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xd6,0xb5,0xd6,0xb5,
+0xd6,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x14,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x42,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0x18,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x08,0x75,0xad,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0xcb,0x5a,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0x94,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x17,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x17,0xbe,
+0x18,0xc6,0x18,0xc6,0x55,0xad,0x34,0xa5,0x54,0xa5,0x55,0xad,0x96,0xb5,0x6d,0x6b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x95,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xd6,0xb5,0xd7,0xb5,0xd6,0xb5,0xb6,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd6,0xbd,0xb7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xb5,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x8a,0x52,0x18,0xc6,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0x17,0xbe,0x17,0xbe,0x17,0xbe,0xf8,0xbd,0x17,0xbe,0xf8,0xbd,0x38,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x76,0xad,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x55,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0xa7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xd2,0x9c,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x75,0xad,0x34,0xa5,
+0x55,0xad,0x76,0xb5,0x71,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd6,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xad,0x75,0xad,
+0x75,0xad,0x55,0xad,0x55,0xad,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xf7,0xbd,
+0xb6,0xb5,0xd6,0xb5,0xb7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,
+0xd7,0xb5,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xc6,0x14,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x52,0x18,0xc6,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0x17,0xc6,0x17,0xbe,0x38,0xc6,0xb2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0x75,0xad,
+0x18,0xc6,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0xcb,0x5a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xb6,0xb5,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x94,0x38,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x17,0xc6,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x18,0xbe,
+0x18,0xc6,0x18,0xc6,0x75,0xad,0x34,0xa5,0x75,0xad,0x14,0xa5,0xe3,0x18,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xf3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xb7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0x96,0xb5,0x96,0xb5,0x76,0xb5,0x75,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0xa6,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x30,0x84,0xd7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd7,0xb5,0xd7,0xb5,
+0xd7,0xbd,0xd7,0xb5,0xd6,0xb5,0xd6,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x8a,0x52,0x18,0xc6,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xc5,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf8,0xc5,
+0x17,0xbe,0xf7,0xc5,0x17,0xbe,0x18,0xc6,0x17,0xc6,0x18,0xbe,0x38,0xc6,0xb2,0x94,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x41,0x08,0x76,0xad,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x58,0xc6,
+0x55,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0x18,0xd6,0xb5,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0xc7,0x39,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0c,0x63,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x96,0xad,0x55,0xad,
+0x75,0xad,0x29,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x9d,0x18,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,0x95,0xad,0x75,0xad,
+0x55,0xad,0x55,0xad,0x55,0xad,0xa6,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x84,0xf7,0xbd,
+0xb7,0xbd,0xd6,0xb5,0xb7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd6,0xb5,0xb6,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xb5,0xd6,0xbd,0xd7,0xbd,0xd6,0xbd,
+0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xc6,0x34,0xa5,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0x4a,0x38,0xc6,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,
+0x17,0xbe,0xf7,0xbd,0x17,0xc6,0xf7,0xbd,0xf7,0xc5,0x17,0xbe,0x18,0xc6,0x17,0xbe,
+0xf8,0xc5,0x17,0xbe,0x38,0xc6,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0x96,0xb5,
+0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x58,0xc6,0xcb,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xd6,0xb5,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x8c,0x18,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x96,0xb5,0x75,0xad,0x4d,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd3,0x9c,0x18,0xc6,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd6,0xbd,0xb6,0xbd,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0x96,0xb5,0x95,0xb5,0x75,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x86,0x31,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x84,0xf7,0xbd,0xd6,0xb5,0xd6,0xbd,0xd6,0xb5,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xb5,0xd7,0xbd,
+0xd6,0xb5,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0x18,0xc6,0x34,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x65,0x29,0xf7,0xbd,0x18,0xc6,0xf8,0xc5,0x17,0xbe,0x17,0xc6,
+0x17,0xbe,0x18,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x17,0xc6,0x18,0xbe,0x17,0xbe,
+0x18,0xc6,0x18,0xc6,0x18,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xc6,0x58,0xc6,0xcf,0x7b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xf3,0x9c,0x59,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,
+0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,0x38,0xc6,0x18,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x58,0xc6,0x58,0xce,0x71,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0xa5,0x59,0xce,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x58,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x58,0xc6,0x38,0xc6,0x58,0xc6,0x38,0xc6,0x58,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x58,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x58,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x59,0xc6,0xb6,0xb5,0x82,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,0x86,0x31,0x0c,0x63,0x30,0x84,0xf3,0x9c,0x75,0xad,
+0xf7,0xbd,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x18,0xc6,0x18,0xc6,
+0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0x18,0xc6,0xb6,0xb5,0x51,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x63,0x18,0xc6,
+0x18,0xc6,0x17,0xbe,0x18,0xc6,0x18,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x95,0xb5,0x75,0xad,
+0x75,0xad,0x75,0xad,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x6b,0xf7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0xf7,0xbd,0xf7,0xbd,0xf8,0xbd,0x17,0xbe,
+0xf7,0xc5,0x17,0xbe,0x17,0xc6,0x17,0xbe,0x17,0xc6,0x38,0xc6,0x10,0x84,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xae,0x73,
+0xd7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0x17,0xbe,0x17,0xbe,0x18,0xc6,0x17,0xbe,
+0xf8,0xbd,0x17,0xbe,0x18,0xc6,0x17,0xbe,0x18,0xbe,0x18,0xc6,0x18,0xc6,0x17,0xc6,
+0x18,0xc6,0xf7,0xbd,0xf3,0x9c,0x62,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,0x65,0x29,
+0x35,0xad,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,
+0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,0xf7,0xbd,0x17,0xbe,
+0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd7,0xbd,
+0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xd7,0xbd,0xf7,0xbd,
+0xd7,0xbd,0x76,0xad,0x8e,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0x31,0x54,0xa5,
+0xd7,0xbd,0xd7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xf7,0xbd,0xd7,0xbd,0xd6,0xb5,
+0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xd6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,
+0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0xb6,0xb5,0x96,0xb5,0x96,0xb5,
+0x54,0xa5,0x08,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,0x29,0x4a,0x8e,0x73,0x71,0x8c,
+0x34,0xa5,0x96,0xb5,0x17,0xbe,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,0x38,0xc6,
+0x18,0xc6,0x38,0xc6,0x55,0xad,0xa2,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x6b,0x34,0xa5,0x34,0xa5,0x34,0xa5,0x34,0xa5,
+0x34,0xa5,0x34,0xa5,0x14,0xa5,0x14,0xa5,0x14,0xa5,0x13,0x9d,0xf3,0x9c,0xf3,0x9c,
+0xf3,0x9c,0xd3,0x9c,0xd3,0x9c,0xb2,0x94,0xb2,0x94,0xef,0x7b,0x04,0x21,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x84,0x55,0xad,0x55,0xad,0x75,0xad,0x55,0xad,
+0x75,0xad,0x55,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,
+0x55,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x55,0xad,0x75,0xad,
+0x55,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x55,0xad,0x75,0xad,0x75,0xad,
+0x75,0xad,0x31,0x8c,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,0x24,0x21,0xc7,0x39,0xc7,0x39,0xc7,0x39,
+0xc7,0x39,0xc7,0x39,0xa7,0x39,0xc7,0x39,0xc7,0x39,0xc7,0x39,0xa7,0x39,0xc7,0x39,
+0xc7,0x39,0xc7,0x39,0xa7,0x39,0xc7,0x39,0xc7,0x39,0x86,0x31,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0x66,0x31,0x66,0x31,
+0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,
+0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,
+0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,
+0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,
+0x65,0x29,0x66,0x31,0x65,0x29,0x66,0x31,0x45,0x29,0x24,0x21,0x24,0x21,0x24,0x21,
+0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,
+0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x24,0x21,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x21,0x24,0x21,0x24,0x21,0x24,0x21,
+0x24,0x21,0x24,0x29,0x24,0x21,0xe3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,0xc3,0x18,
+0xc3,0x18,0xc3,0x18,0x61,0x08,0x41,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,0x82,0x10,0x86,0x31,0xaa,0x52,
+0xef,0x7b,0xd3,0x9c,0x75,0xad,0xd6,0xb5,0xf7,0xbd,0xb6,0xb5,0x8a,0x52,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0xc6,0x00,0xc5,0x00,0xc6,0x00,
+0xc5,0x00,0x85,0x00,0x84,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x41,0x08,0xa2,0x10,0x82,0x10,0xa2,0x10,0x82,0x10,0xa2,0x10,0x82,0x10,0xa2,0x10,
+0x82,0x10,0xa2,0x10,0x82,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0x82,0x10,0xa2,0x10,
+0xa2,0x10,0xa2,0x10,0x82,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,
+0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,0xa2,0x10,
+0xa3,0x10,0xa2,0x10,0xa2,0x18,0xa3,0x10,0x82,0x10,0x21,0x08,0x21,0x08,0x20,0x08,
+0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,
+0x21,0x08,0x21,0x08,0x21,0x08,0x20,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,
+0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,
+0x21,0x08,0x21,0x08,0x21,0x08,0x41,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,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,0x21,
+0x66,0x31,0x61,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,
+0xd6,0x33,0x99,0x44,0x78,0x44,0x78,0x44,0x58,0x44,0x58,0x44,0x98,0x4c,0x99,0x54,
+0x78,0x54,0xb5,0x3b,0x6f,0x1a,0x28,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,0x01,0x00,
+0x69,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x12,0x99,0x44,0x99,0x44,0x99,0x44,
+0x99,0x44,0x79,0x44,0x99,0x44,0xda,0x4c,0x1b,0x5d,0x3c,0x65,0xfb,0x4c,0x79,0x34,
+0xb5,0x23,0xcb,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x23,0x79,0x3c,0xc6,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x23,0xb9,0x44,0x79,0x44,0x79,0x44,0x78,0x44,0x79,0x44,0x78,0x44,
+0x99,0x4c,0xfa,0x5c,0x1b,0x65,0xfb,0x54,0x9a,0x3c,0x59,0x24,0xd1,0x22,0x00,0x00,
+0x00,0x00,0x00,0x00,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,0x0a,0x79,0x3c,
+0x79,0x3c,0x4e,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xf6,0x33,0x99,0x44,
+0x78,0x44,0x79,0x44,0x78,0x44,0x78,0x44,0x78,0x44,0x99,0x44,0xda,0x54,0x1b,0x5d,
+0xfb,0x54,0x9a,0x3c,0x59,0x24,0x72,0x3b,0x20,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,0xa6,0x00,0x37,0x34,0x79,0x3c,0x79,0x3c,0xb5,0x2b,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x01,0x58,0x44,0x79,0x44,0x78,0x44,0x78,0x44,0x78,0x44,
+0x58,0x44,0x58,0x3c,0x78,0x44,0xb9,0x4c,0x1b,0x5d,0x1b,0x5d,0xba,0x44,0x79,0x2c,
+0xb2,0x5b,0xa1,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x2b,0x79,0x3c,0x58,0x3c,
+0x79,0x3c,0x58,0x3c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x12,
+0x99,0x44,0x78,0x44,0x78,0x44,0x78,0x44,0x78,0x44,0x58,0x44,0x58,0x3c,0x58,0x44,
+0x99,0x4c,0xfa,0x5c,0x1b,0x5d,0xba,0x44,0x78,0x4c,0xf0,0x7b,0x24,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xb0,0x1a,0x79,0x3c,0x58,0x3c,0x58,0x3c,0x78,0x3c,0x99,0x3c,0x6f,0x12,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x23,0x99,0x44,0x58,0x44,0x78,0x44,
+0x58,0x44,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x79,0x44,0xda,0x54,0x1b,0x5d,
+0xda,0x4c,0xd5,0x84,0x50,0x8c,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x01,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x79,0x3c,0xb5,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xd6,0x33,0x79,0x44,0x58,0x44,0x58,0x44,0x58,0x44,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x58,0x3c,0x79,0x44,0xda,0x54,0x1b,0x5d,0x18,0x85,0x13,0xa5,0x71,0x8c,
+0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,0xf6,0x33,
+0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x78,0x3c,0x79,0x3c,0x58,0x34,0xa6,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x01,0x37,0x3c,0x58,0x44,
+0x58,0x44,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x78,0x44,
+0xba,0x4c,0x59,0x8d,0x96,0xb5,0x14,0xa5,0x92,0x94,0xeb,0x5a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x33,0x23,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x58,0x3c,0x58,0x34,0xed,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x2d,0x12,0x78,0x44,0x78,0x44,0x58,0x44,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x58,0x44,0x58,0x3c,0x58,0x3c,0x79,0x34,0x59,0x85,0x58,0xce,0xd6,0xb5,
+0x34,0xa5,0xb2,0x94,0x6d,0x6b,0x20,0x00,0x00,0x00,0x2e,0x12,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x78,0x3c,0x58,0x34,0x38,0x2c,0xf2,0x12,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0x1a,
+0x74,0x2b,0x94,0x2b,0xb5,0x33,0xb5,0x33,0xd5,0x33,0xd6,0x33,0xf6,0x33,0xf6,0x33,
+0xd6,0x23,0xf7,0x7c,0x9a,0xd6,0x59,0xce,0xd7,0xbd,0x55,0xad,0xd3,0x9c,0xae,0x73,
+0xa8,0x21,0xf7,0x33,0x38,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,
+0x58,0x3c,0x38,0x34,0xf7,0x23,0x74,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x00,0x02,0x00,0x23,0x00,0x23,0x00,0x01,0x00,0xec,0x5a,0xba,0xd6,0x9a,0xd6,
+0x79,0xce,0xf7,0xbd,0x75,0xad,0xd3,0x9c,0x51,0x84,0x36,0x4c,0x38,0x34,0x58,0x3c,
+0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x17,0x2c,0xf7,0x1b,0x95,0x23,
+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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x10,0xec,0x5a,
+0x30,0x84,0x8e,0x73,0x20,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xe7,0x39,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0x99,0xce,0x18,0xc6,0x96,0xb5,
+0xd2,0x9c,0xd4,0x43,0x38,0x34,0x38,0x3c,0x38,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,
+0x58,0x34,0x17,0x24,0xd6,0x1b,0xb5,0x23,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x69,0x4a,0x0f,0x7c,0x71,0x8c,0xd3,0x9c,0x55,0xad,0xb2,0x94,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0xba,0xd6,0x9a,0xd6,
+0x9a,0xd6,0x9a,0xd6,0x99,0xd6,0x59,0xce,0x0f,0x84,0xcc,0x01,0x58,0x3c,0x38,0x3c,
+0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x37,0x2c,0xf6,0x23,0xb5,0x13,0x53,0x23,
+0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa7,0x39,0xae,0x73,0x51,0x8c,0xb2,0x94,0x14,0xa5,
+0x75,0xad,0xf7,0xbd,0x79,0xce,0xd2,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xe7,0x39,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0xba,0xd6,0x38,0xc6,
+0xc3,0x18,0x24,0x00,0x17,0x34,0x58,0x34,0x58,0x3c,0x58,0x3c,0x58,0x3c,0x58,0x34,
+0x17,0x2c,0xd6,0x1b,0x95,0x13,0xd0,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x29,0x6d,0x6b,0x51,0x8c,
+0x92,0x94,0xf3,0x9c,0x55,0xad,0xd6,0xb5,0x38,0xc6,0x79,0xce,0x9a,0xd6,0xba,0xd6,
+0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0x39,0x9a,0xd6,0x9a,0xd6,
+0x99,0xd6,0x9a,0xd6,0x9a,0xd6,0x8a,0x52,0x00,0x00,0x00,0x00,0x74,0x23,0x58,0x3c,
+0x58,0x3c,0x58,0x3c,0x58,0x3c,0x38,0x34,0xf7,0x23,0xd6,0x13,0x94,0x1b,0xa9,0x21,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x10,
+0xeb,0x5a,0x30,0x84,0x71,0x94,0xd3,0x9c,0x34,0xa5,0x96,0xb5,0xf7,0xbd,0x79,0xce,
+0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0xba,0xd6,0x79,0xce,0xa6,0x31,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc7,0x39,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0xba,0xd6,0x51,0x8c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x0d,0x12,0x58,0x3c,0x58,0x34,0x58,0x3c,0x58,0x3c,0x37,0x2c,
+0xd6,0x0b,0x95,0x03,0xd2,0x5b,0x41,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,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x8a,0x4a,0x11,0x74,0x72,0x84,0xb3,0x8c,0x14,0x9d,0x75,0xb5,
+0xf7,0xbd,0x58,0xce,0x99,0xce,0x9a,0xd6,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,
+0xba,0xd6,0xd7,0xbd,0x41,0x08,0x00,0x00,0x00,0x00,0x86,0x31,0x79,0xce,0x9a,0xd6,
+0xba,0xd6,0x96,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x17,0x34,
+0x58,0x3c,0x58,0x34,0x38,0x24,0xd7,0x03,0x16,0x3c,0xb5,0x84,0x6d,0x6b,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+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,0x22,0x15,0x4c,0x78,0x4c,0xb9,0x4c,
+0xfa,0x54,0xfa,0x64,0xf9,0x64,0x39,0x85,0xd9,0xad,0x39,0xc6,0xba,0xd6,0xda,0xd6,
+0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0xba,0xd6,0x9a,0xd6,0xda,0xd6,0xd3,0x9c,0x00,0x00,
+0x00,0x00,0x86,0x31,0x79,0xce,0xba,0xd6,0x59,0xce,0x65,0x29,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x13,0x58,0x2c,0x78,0x4c,0xf8,0x74,0x78,0x95,
+0xb7,0xb5,0x54,0xad,0x24,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa5,0x00,0xb5,0x33,
+0x79,0x2c,0x9a,0x2c,0xdb,0x44,0xfb,0x54,0xfb,0x54,0xda,0x54,0xda,0x4c,0xba,0x4c,
+0x99,0x44,0xc8,0x21,0xe8,0x41,0x92,0x94,0xd7,0xbd,0x9a,0xd6,0xda,0xd6,0xba,0xd6,
+0xba,0xd6,0x9a,0xd6,0xba,0xd6,0x2c,0x63,0x00,0x00,0xe4,0x20,0xf7,0xbd,0xba,0xd6,
+0x0c,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0x5b,
+0xb9,0x9d,0x59,0xbe,0x9a,0xd6,0x59,0xce,0xd7,0xbd,0x10,0x84,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x85,0x00,0xf7,0x2b,0x9a,0x2c,0xba,0x44,0xfb,0x54,0xfb,0x5c,0xfa,0x54,
+0xda,0x54,0xda,0x54,0xba,0x54,0xda,0x54,0xf6,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa7,0x39,0xcf,0x7b,0x96,0xb5,0x59,0xce,0xba,0xd6,0xdb,0xde,0x96,0xb5,
+0x00,0x00,0x00,0x00,0xe3,0x18,0xc7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x29,0x4a,0x92,0x94,0xf7,0xbd,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0x79,0xce,0x18,0xbe,
+0x75,0xad,0xe7,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb5,0x2b,0xbb,0x3c,0xdb,0x4c,
+0x1b,0x5d,0xfb,0x5c,0xfa,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,
+0x8e,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x45,0x29,0x4d,0x6b,0x34,0xa5,0x08,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x08,0x42,0x92,0x94,0xf7,0xbd,0xba,0xd6,0xba,0xd6,0xba,0xd6,0x9a,0xd6,
+0x9a,0xd6,0x9a,0xd6,0x59,0xce,0xf7,0xbd,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x8f,0x1a,0xfb,0x4c,0x1b,0x5d,0x1b,0x5d,0xfa,0x5c,0xfa,0x54,0xda,0x54,0xda,0x54,
+0xda,0x54,0xda,0x54,0xda,0x54,0x99,0x4c,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0x31,0x9a,0xd6,0xba,0xd6,0xba,0xd6,
+0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0x99,0xce,0x38,0xc6,0xb6,0xb5,
+0xab,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0xb9,0x54,0x3b,0x5d,0x1b,0x5d,0xfa,0x54,
+0xfa,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xb5,0x3b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x24,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x45,0x29,0x38,0xc6,0xda,0xd6,0xba,0xd6,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,
+0x9a,0xd6,0x79,0xce,0xf7,0xbd,0x14,0xa5,0x61,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,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x22,
+0x3c,0x5d,0x1b,0x5d,0xfa,0x54,0xfa,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,
+0xda,0x54,0xda,0x54,0xda,0x54,0x0b,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x31,0xae,0x73,0xb6,0xb5,0x79,0xce,0x8e,0x73,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x20,0xeb,0x5a,0x34,0xa5,
+0x38,0xc6,0xba,0xd6,0xba,0xd6,0xba,0xd6,0x9a,0xd6,0x58,0xc6,0xb6,0xb5,0x8d,0x6b,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x4c,0x1b,0x5d,0xfb,0x54,0xfa,0x54,0xda,0x54,
+0xfa,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0x78,0x4c,0x02,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x41,0x30,0x84,0xd7,0xb5,0x9a,0xd6,
+0xda,0xd6,0xba,0xd6,0xdb,0xde,0x75,0xad,0x00,0x00,0x00,0x00,0x8a,0x52,0x8e,0x73,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x18,0xaa,0x52,0xf3,0x9c,0x18,0xc6,
+0x9a,0xd6,0x38,0xc6,0x55,0xad,0x24,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x01,0xfb,0x5c,
+0xfb,0x5c,0xfb,0x54,0xfb,0x54,0xfa,0x54,0xfa,0x54,0xfa,0x54,0xda,0x54,0xfa,0x54,
+0xfb,0x54,0xba,0x54,0xaf,0x22,0x00,0x00,0x00,0x00,0x49,0x4a,0x92,0x94,0x38,0xc6,
+0xba,0xd6,0xda,0xd6,0xba,0xd6,0xba,0xd6,0x9a,0xd6,0xba,0xd6,0x79,0xce,0x86,0x31,
+0x00,0x00,0x45,0x29,0x9a,0xd6,0xdb,0xde,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x10,0x08,0x42,0x10,0x7c,0x32,0x74,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x2b,0x1b,0x5d,0xfb,0x5c,0xfb,0x5c,0xfb,0x5c,0xfb,0x5c,
+0x1b,0x55,0xfb,0x54,0x98,0x4c,0xb5,0x3b,0x4d,0x1a,0xc5,0x00,0x00,0x00,0x00,0x00,
+0x10,0x84,0xf7,0xbd,0xba,0xd6,0xfb,0xde,0xdb,0xde,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,
+0xba,0xd6,0xba,0xd6,0x6d,0x6b,0x00,0x00,0x00,0x00,0x66,0x31,0x79,0xce,0xba,0xd6,
+0xba,0xd6,0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x45,0x00,0x54,0x23,0x58,0x34,0xf6,0x33,0xf2,0x22,0x69,0x01,0x02,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x4c,0x1b,0x5d,
+0x1b,0x5d,0x1b,0x5d,0xfb,0x5c,0x58,0x4c,0x53,0x33,0xea,0x11,0x43,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x7b,0x96,0xb5,0x59,0xce,0xdb,0xde,
+0xdb,0xde,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0xdb,0xd6,0x34,0xa5,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0x79,0xce,0xba,0xd6,0xba,0xd6,0x58,0xc6,0x45,0x29,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x12,0x38,0x3c,0x99,0x44,0x79,0x44,0x99,0x44,
+0x99,0x44,0x99,0x44,0x17,0x3c,0x12,0x23,0x89,0x01,0x02,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x26,0x01,0x1b,0x5d,0xda,0x54,0x16,0x44,0xef,0x2a,0x47,0x09,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xaa,0x52,0x75,0xad,0x38,0xc6,0xda,0xd6,0xfb,0xde,0xba,0xd6,0xba,0xd6,0xba,0xd6,
+0x18,0xc6,0xe3,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x31,0x79,0xce,0xba,0xd6,
+0x9a,0xd6,0xba,0xd6,0xb6,0xb5,0x00,0x00,0x00,0x00,0x85,0x00,0x74,0x2b,0x99,0x44,
+0x79,0x44,0x79,0x44,0x79,0x44,0x79,0x44,0x79,0x44,0x79,0x44,0x99,0x44,0xba,0x44,
+0xb9,0x44,0x17,0x3c,0x12,0x23,0x89,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0xea,0x11,0xc5,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x29,0x54,0xa5,0xf7,0xbd,0xba,0xd6,
+0xfb,0xde,0xda,0xd6,0xba,0xd6,0xba,0xd6,0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0x79,0xce,0xba,0xd6,0x9a,0xd6,0x9a,0xd6,0xda,0xd6,0x92,0x94,
+0xab,0x01,0x37,0x3c,0x99,0x44,0x78,0x44,0x79,0x44,0x79,0x44,0x79,0x44,0x79,0x44,
+0x79,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x9a,0x44,0xba,0x44,0xba,0x44,
+0x38,0x3c,0x53,0x23,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x41,0x08,0xb2,0x94,0xd7,0xb5,0x79,0xce,0xfb,0xde,0xdb,0xde,0xda,0xde,0x10,0x84,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x31,0x79,0xce,0xba,0xd6,
+0x9a,0xd6,0x9a,0xd6,0x9a,0xd6,0xba,0xd6,0x59,0x85,0x79,0x34,0x79,0x44,0x79,0x44,
+0x99,0x44,0x79,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,
+0x99,0x44,0x99,0x44,0x99,0x44,0x9a,0x44,0xda,0x44,0x79,0x44,0x07,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x84,0x96,0xb5,0x59,0xce,
+0xdb,0xde,0xfb,0xde,0x3a,0xbe,0xc9,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0x79,0xce,0xda,0xd6,0xba,0xd6,0xba,0xd6,0xba,0xd6,0xba,0xd6,
+0x9a,0xce,0xf9,0x6c,0x59,0x34,0x79,0x44,0x79,0x44,0x99,0x44,0x99,0x44,0x99,0x44,
+0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0x99,0x44,0xba,0x44,0xba,0x44,
+0xb5,0x2b,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x63,0x75,0xad,0x18,0xc6,0xda,0xde,0xdb,0xd6,0x3a,0x75,0x99,0x44,
+0x6d,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x29,0xba,0xd6,0x1c,0xe7,
+0xfb,0xde,0xfb,0xde,0xfb,0xde,0xdb,0xde,0xfb,0xde,0x7a,0xc6,0x98,0x4c,0x38,0x2c,
+0x58,0x34,0x58,0x34,0x58,0x34,0x79,0x3c,0x79,0x3c,0x79,0x3c,0x79,0x3c,0x79,0x3c,
+0x99,0x3c,0x9a,0x44,0x79,0x44,0xb0,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe7,0x39,0x55,0xad,0xf7,0xbd,
+0xba,0xd6,0xda,0x9d,0xba,0x44,0xda,0x54,0xda,0x54,0x73,0x33,0x02,0x00,0x00,0x00,
+0x00,0x00,0x65,0x29,0xda,0xde,0x1c,0xe7,0x1b,0xdf,0x1c,0xe7,0x1b,0xdf,0x1c,0xdf,
+0x1c,0xe7,0x3c,0xe7,0x1a,0xb6,0xd6,0x13,0xd6,0x13,0xf6,0x23,0xf7,0x23,0x17,0x24,
+0x17,0x24,0x17,0x24,0x17,0x24,0x38,0x2c,0x38,0x2c,0xb5,0x23,0x28,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa3,0x18,0xf3,0x9c,0xd7,0xbd,0xd9,0xa5,0xba,0x4c,0xda,0x4c,0xda,0x54,
+0xda,0x54,0xda,0x54,0x37,0x44,0x07,0x01,0x00,0x00,0xa7,0x39,0x59,0xce,0x79,0xce,
+0x99,0xce,0x9a,0xd6,0xba,0xd6,0xba,0xd6,0xba,0xd6,0xdb,0xde,0xfb,0xde,0x58,0x95,
+0x74,0x03,0x95,0x03,0x95,0x1b,0x95,0x1b,0xb5,0x1b,0xb5,0x1b,0xd6,0x1b,0xd6,0x1b,
+0x6f,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8c,0x96,0xad,
+0x98,0x54,0x99,0x3c,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0x99,0x4c,
+0x48,0x01,0x00,0x00,0x0c,0x63,0x8e,0x73,0x30,0x84,0x92,0x94,0xf3,0x9c,0x34,0xa5,
+0x75,0xad,0xb6,0xb5,0x18,0xbe,0x58,0xc6,0x16,0x95,0x93,0x3b,0x33,0x0b,0x53,0x13,
+0x53,0x13,0x73,0x1b,0xd0,0x1a,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x8d,0x73,0xf6,0x8c,0x17,0x0c,0x99,0x44,0xda,0x54,0xda,0x54,
+0xda,0x54,0xda,0x54,0xda,0x54,0xfb,0x54,0xcf,0x22,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0xe4,0x20,0x86,0x31,0x08,0x42,
+0xeb,0x5a,0xcc,0x52,0x4c,0x32,0x4d,0x1a,0x0c,0x1a,0xe6,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0x52,0x55,0x64,
+0xf7,0x03,0x79,0x3c,0xda,0x4c,0xfa,0x54,0xda,0x54,0xda,0x54,0xda,0x54,0xfa,0x54,
+0xaf,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x45,0x29,0xf5,0x4b,0xf7,0x03,0x58,0x34,0xda,0x4c,0xda,0x54,
+0xda,0x54,0xda,0x54,0xfa,0x54,0xfb,0x54,0xcf,0x22,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0x52,0x33,
+0xd6,0x0b,0x38,0x2c,0xba,0x4c,0xfa,0x54,0xfa,0x54,0xfa,0x54,0xda,0x54,0xfb,0x54,
+0xaf,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x2a,0xd6,0x13,0x18,0x24,0x99,0x44,0xfb,0x54,
+0xfb,0x54,0xfb,0x54,0xfa,0x54,0xfb,0x54,0xcf,0x22,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x11,
+0xd6,0x23,0x17,0x1c,0x79,0x3c,0xfa,0x54,0xfb,0x54,0xfb,0x54,0xfb,0x54,0x1b,0x55,
+0x8e,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x22,0x18,0x1c,0x79,0x34,0xda,0x54,
+0xfb,0x54,0xfb,0x54,0xfb,0x54,0x1b,0x5d,0x8d,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x1b,0x59,0x2c,0xda,0x4c,0xfb,0x54,0xfb,0x54,0xfb,0x54,0x1b,0x55,
+0x8d,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x1a,0xda,0x4c,
+0x1b,0x55,0xfb,0x5c,0xfb,0x54,0x1b,0x5d,0x6c,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x1a,0xda,0x54,0x1b,0x5d,0xfb,0x54,0x1b,0x5d,
+0x2b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x67,0x09,0x78,0x4c,0x3c,0x5d,0x1c,0x5d,0x2b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,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,0x73,0x33,0x3c,0x5d,
+0x2b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00};
+#endif
diff --git a/lib/tizen/tizen_logo_16bpp_gzip.h b/lib/tizen/tizen_logo_16bpp_gzip.h
new file mode 100644
index 00000000..d8526f88
--- /dev/null
+++ b/lib/tizen/tizen_logo_16bpp_gzip.h
@@ -0,0 +1,647 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2013 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#ifndef __TIZEN_LOGO_16BPP_GZIP__
+#define __TIZEN_LOGO_16BPP_GZIP__
+
+/* Format: GZIP: BMP RGB565 16BPP 452x140 */
+unsigned char tizen_logo_16bpp_gzip[] = {
+0x1f,0x8b,0x08,0x08,0xd9,0x76,0x29,0x53,0x00,0x03,0x74,0x69,0x7a,0x65,0x6e,0x5f,
+0x6c,0x6f,0x67,0x6f,0x2e,0x62,0x6d,0x70,0x00,0xed,0x9d,0x6f,0x6c,0x1b,0x67,0x7e,
+0xe7,0xa9,0x4d,0x80,0x65,0xbb,0x2e,0x56,0xb1,0xd8,0x25,0xcf,0x0a,0x70,0x52,0xa4,
+0x2d,0xc2,0x5a,0x39,0x58,0x35,0xf7,0x42,0x35,0x7a,0x63,0xd5,0x6a,0x1b,0x9d,0x5c,
+0xd4,0x0a,0x85,0xca,0xde,0x35,0x70,0x1b,0xc7,0x29,0xbc,0xaa,0xbb,0x50,0x14,0x0a,
+0xd6,0x79,0xdf,0x9c,0x2b,0x07,0x88,0xa1,0xb8,0x88,0x4a,0x11,0x2b,0x83,0x7a,0x71,
+0xc9,0xd2,0x6e,0x1d,0x4c,0x76,0xa1,0x60,0x28,0x44,0xc5,0xe8,0x8d,0x6b,0xba,0xbd,
+0x14,0xca,0x56,0xba,0x0e,0x51,0x05,0x70,0x0b,0x24,0xa8,0x83,0x7a,0xef,0x5c,0x54,
+0x77,0x61,0x6a,0xbf,0xb9,0x79,0xe6,0x99,0xe7,0x79,0x7e,0xf3,0x87,0x9c,0x67,0x86,
+0xc3,0x7f,0xca,0xf3,0x7d,0x30,0x1a,0x92,0xe2,0x9f,0x21,0x39,0x1f,0x7e,0x7f,0xcf,
+0xbf,0xdf,0x33,0x72,0xe2,0xc6,0xff,0xe9,0x08,0x21,0xfd,0xb6,0xb6,0x25,0xb5,0xed,
+0xaf,0xb4,0xab,0x8b,0xda,0xbe,0x23,0xd4,0x19,0x7a,0x42,0xdb,0xff,0x57,0xed,0xff,
+0x1d,0xfa,0x75,0xa0,0x2f,0x43,0xa1,0x7f,0xfa,0x7a,0x28,0xf4,0x1f,0x43,0x42,0x42,
+0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x5f,0x3d,0xf5,0x86,0xdf,0x18,0x3c,0x17,0x3f,
+0x16,0x6e,0xf6,0x71,0x08,0x09,0xb5,0x8a,0x7a,0xc3,0x3d,0xa1,0x1e,0xb4,0x91,0x42,
+0x2f,0xf7,0x6a,0x5b,0x3d,0x74,0x6b,0x22,0x91,0x2f,0xc8,0x59,0x39,0x91,0xdf,0xce,
+0x3c,0xbc,0xf4,0xe0,0x74,0x78,0xe4,0xc9,0xde,0xba,0xbc,0x50,0xcb,0xab,0xa7,0x6e,
+0xcf,0xfc,0xfd,0xf0,0x1f,0x4f,0xcf,0x2c,0x9e,0xd4,0xcb,0x8c,0xbe,0xcd,0x2c,0xce,
+0xd0,0x6b,0x27,0x8d,0x6b,0x57,0x27,0xfc,0x3e,0xff,0xb3,0x23,0x9d,0x0b,0x6b,0x99,
+0xb5,0xcc,0xb6,0xb1,0x59,0xcb,0x76,0x95,0x6b,0xe8,0xfa,0x36,0x78,0xac,0x76,0x2d,
+0x67,0x5c,0xce,0x6d,0xeb,0xff,0xfb,0x80,0x6e,0x7b,0x39,0x52,0x96,0x32,0xe1,0x11,
+0xde,0xa3,0xfb,0x34,0x76,0x64,0x81,0x3d,0x92,0xbf,0x44,0xf2,0x55,0xcb,0x6a,0x85,
+0xcb,0x0e,0xd7,0x13,0xf9,0x23,0x0b,0x2f,0x77,0xf2,0x1d,0x6d,0x6f,0xb8,0x73,0x21,
+0x91,0x77,0x2b,0x47,0x16,0x79,0x9f,0x8f,0x4f,0xf7,0x87,0x22,0x1a,0x85,0xb8,0xa8,
+0x5a,0x41,0xfb,0xb4,0xd4,0xb5,0xfa,0x5a,0xe6,0xda,0xec,0xd5,0x89,0x1b,0x83,0xef,
+0x04,0xfa,0x6a,0xcd,0x54,0x78,0x64,0x2d,0xe3,0xf6,0xad,0xef,0xe5,0x06,0xa6,0xeb,
+0xf1,0xda,0x4b,0x99,0x92,0xa2,0xca,0x25,0xb9,0xa4,0xa0,0x0d,0x7d,0xce,0xf8,0x92,
+0x7e,0xab,0xa2,0x2a,0x25,0xa3,0xbc,0x77,0xda,0xcf,0xb3,0x3f,0xbc,0x84,0x9f,0x8b,
+0xb7,0x94,0xc1,0x9e,0x6f,0x2b,0x3b,0xdc,0x56,0x90,0xef,0x0e,0xf1,0x1d,0xdf,0x4e,
+0xce,0xe9,0xf1,0x7c,0x5b,0x50,0xa5,0xac,0x9c,0x5c,0xe4,0x3b,0xda,0x23,0x0b,0xf0,
+0x75,0xf5,0xef,0xc7,0xf8,0x74,0xf5,0xef,0x49,0xff,0xbe,0x54,0x0f,0xcf,0xc7,0xa3,
+0xdb,0xb1,0xa5,0x0c,0xe3,0x10,0x16,0xd5,0xa0,0x72,0x32,0xbf,0x93,0x3b,0xb2,0x30,
+0x70,0xf6,0x59,0xee,0x5f,0xbf,0xd6,0xd4,0xed,0xd8,0xa4,0xe4,0xf4,0x3e,0xed,0xc5,
+0xbf,0x2b,0x55,0xd2,0xb9,0x41,0xbe,0x57,0x2e,0x29,0x4b,0x19,0xef,0xcf,0x3e,0x70,
+0xb6,0xa4,0xb0,0x6f,0xad,0x60,0xfc,0x96,0xb2,0xcb,0xf0,0x36,0xf2,0xbd,0xaa,0xf4,
+0xfb,0x55,0x4d,0xb7,0xb2,0xfb,0x94,0xd0,0x5f,0x05,0xef,0xf5,0x5f,0x0e,0x6d,0x2b,
+0x68,0xdb,0xba,0x76,0x7d,0x5d,0xbf,0xbd,0xac,0xbc,0x3f,0xcb,0x73,0x7c,0xa3,0xf1,
+0x2c,0xfd,0xed,0xc1,0xdb,0x3a,0xd9,0xcb,0x78,0xa3,0xcf,0x4d,0x36,0x19,0x5f,0x2f,
+0x81,0x6d,0x5d,0x66,0x8f,0x55,0xe1,0xfd,0x8c,0xe3,0xc6,0xc7,0x8b,0xf6,0xf6,0xf7,
+0x58,0xd0,0x1f,0x9b,0xca,0xf3,0x7d,0x9e,0x89,0x3c,0x7a,0x1d,0xf8,0x99,0x39,0x7f,
+0x57,0x93,0x52,0x70,0x8e,0xd8,0xa9,0xc7,0x0b,0xd9,0x0a,0xaf,0x95,0xa5,0xdf,0x27,
+0xfa,0xfb,0xb6,0x8f,0x73,0xa4,0x75,0xf4,0xe2,0x18,0x7a,0x3f,0xee,0x45,0x95,0x3b,
+0x17,0x82,0x7e,0xed,0x1b,0x9c,0x1c,0xaa,0xca,0x9a,0xe7,0xcf,0xb8,0x37,0x9c,0x92,
+0x54,0xa5,0x60,0xfa,0xa6,0xcc,0x44,0x15,0xc0,0xf5,0x02,0xbd,0x8e,0xcf,0x5a,0x72,
+0x26,0xaf,0x93,0x47,0x29,0x6c,0x4f,0xa8,0xa0,0x44,0x2a,0x2a,0xf5,0xf3,0x92,0xee,
+0x08,0x1f,0x5f,0xe2,0x39,0xc2,0x73,0xf1,0x02,0x79,0x1c,0xfa,0xab,0x3f,0x5b,0x89,
+0xdd,0xa2,0x58,0x63,0x03,0xc3,0x7d,0x0c,0xdf,0xa1,0xf1,0x83,0xce,0x52,0xc1,0xb8,
+0xbd,0x80,0x9f,0x49,0xbf,0x5f,0x41,0x66,0xc7,0x49,0x7e,0x25,0x54,0x40,0xb8,0x4e,
+0x39,0xe2,0x50,0xe2,0x69,0x01,0xe9,0xd5,0x39,0x2c,0x58,0x3e,0x2f,0xfb,0x86,0x38,
+0x0c,0x2a,0x56,0x3c,0x31,0x1d,0xd1,0xdc,0xae,0x32,0x87,0xd6,0x5f,0x00,0xbe,0xdf,
+0xbf,0xd6,0x14,0x2f,0x87,0x85,0x26,0x72,0x58,0xf2,0xc1,0xe1,0x89,0x69,0x78,0xd6,
+0x58,0xb8,0x06,0x1b,0xe4,0x52,0x2f,0xc6,0x99,0x5b,0x50,0x0a,0x94,0x34,0xea,0x75,
+0xc6,0x46,0x3c,0x09,0xfa,0x55,0x81,0x9e,0xe5,0xde,0x38,0x34,0xe2,0x6f,0xd9,0x20,
+0x8f,0xb2,0x57,0x32,0x6e,0x03,0xa4,0x1a,0x2c,0xaa,0xc6,0x2b,0x31,0x12,0xf5,0x7b,
+0x62,0x5f,0x54,0x0a,0x32,0x38,0x46,0xe2,0xd9,0x32,0xfb,0xf5,0x20,0xbf,0x40,0xeb,
+0x94,0x61,0x3e,0x6e,0x7a,0x28,0x87,0x4e,0xf4,0x81,0xef,0x4a,0x9e,0x94,0x2e,0x07,
+0xc2,0xe1,0xf9,0x31,0x54,0x1f,0xda,0xce,0xec,0x70,0x71,0x88,0xee,0xb3,0x97,0x0b,
+0xe2,0x75,0x9b,0x23,0x7e,0x0e,0x8f,0xb4,0x11,0x87,0xc7,0xc2,0x93,0x12,0x8e,0xa2,
+0x2a,0x9c,0x39,0xc4,0x27,0x88,0xaf,0x81,0xdb,0x69,0xf4,0xa7,0x9f,0xdf,0xd4,0xf3,
+0x0c,0xa7,0x61,0x6c,0x58,0x58,0x91,0x49,0x6d,0xc9,0x23,0x87,0xc4,0xf9,0x14,0xfc,
+0xec,0xd8,0x05,0x55,0x40,0x3a,0x7d,0x0d,0x52,0x13,0x23,0xff,0x97,0x49,0xbd,0x8c,
+0x1d,0x19,0x39,0x06,0x7a,0x8c,0x94,0x57,0xf2,0x78,0x95,0x1e,0xad,0xf1,0x1e,0x3d,
+0x73,0x68,0xfd,0x35,0x2b,0xc0,0xcf,0x4f,0xe7,0x30,0x08,0x3f,0x1c,0x8d,0xef,0xe5,
+0xba,0x56,0x77,0xb8,0x39,0x2c,0x7c,0x65,0x38,0x6c,0x27,0x3f,0xbc,0x30,0x6d,0xae,
+0xcb,0xa8,0xc0,0xf3,0xac,0xd1,0x28,0xa8,0x05,0x5a,0x3c,0x4f,0x05,0x5e,0x42,0x23,
+0x52,0x19,0x47,0x7f,0xb8,0x2e,0xe6,0xc4,0xa6,0xc7,0xb8,0x14,0x50,0xa3,0x2a,0x86,
+0x37,0xca,0x46,0x9c,0x6a,0x6e,0xbf,0xa2,0x7c,0x12,0x9e,0xf0,0xfd,0x08,0x6d,0xc6,
+0xa3,0x21,0xcb,0x20,0x8a,0x55,0x8d,0xcf,0x83,0x44,0xa9,0x2a,0x8d,0xaa,0xf9,0xfc,
+0x8b,0x70,0xc8,0x3e,0x45,0xf3,0x67,0x48,0x2e,0xab,0x9c,0xcf,0xe7,0xa6,0x99,0xc5,
+0x84,0xe6,0x86,0x3b,0x39,0xd4,0x3e,0x2d,0x38,0x6c,0x4f,0x0e,0xbf,0x8f,0xdc,0xd0,
+0xc6,0x20,0xdb,0xb3,0x96,0x0d,0xd8,0x1a,0x42,0xda,0x33,0x8c,0xf3,0x96,0x9e,0xfb,
+0xcc,0x8b,0x54,0x7a,0x4e,0x97,0x98,0x6b,0x11,0xa7,0xa1,0x35,0x3b,0x9f,0x1c,0x12,
+0x16,0xc1,0x56,0xa2,0x64,0x99,0xdc,0x10,0xb4,0x23,0xc3,0xc7,0xc1,0xa3,0x31,0xdc,
+0x19,0xd7,0x39,0x49,0x24,0xab,0x50,0x07,0x35,0xf6,0xf8,0x79,0xbc,0xf9,0xa1,0xf9,
+0x73,0x34,0xd7,0xb8,0x75,0x3f,0x0c,0x84,0xc3,0x8f,0x2f,0x4d,0xea,0xad,0xf4,0x82,
+0xc3,0xd6,0xe2,0x70,0xdb,0x13,0x87,0xd7,0x66,0xcb,0x0a,0xf4,0x3a,0xab,0x17,0x92,
+0x36,0x46,0xd8,0x4e,0x49,0xfc,0xae,0x24,0x97,0x40,0xc4,0xa7,0x12,0xc6,0x98,0xc3,
+0x18,0x11,0xa1,0xca,0xce,0x65,0xc3,0xa1,0x08,0x45,0x5e,0x39,0x84,0x54,0xa9,0x80,
+0x2c,0x6b,0x31,0x51,0xc8,0xda,0x70,0xd8,0xaf,0x00,0xe5,0x0e,0x1e,0x11,0xf5,0x4e,
+0x56,0x97,0x34,0x7e,0x61,0x0c,0x36,0x3d,0xf9,0x21,0x63,0x0f,0xfe,0xba,0xc1,0x88,
+0x3f,0x08,0x3f,0x7c,0x70,0x3a,0x25,0x25,0xf2,0x5d,0xab,0x98,0xc3,0x35,0x4e,0x0e,
+0xd5,0x7d,0xcf,0x61,0xa1,0xc9,0xed,0xa5,0xde,0xfc,0xf0,0x72,0x67,0x5a,0x22,0x67,
+0x0c,0xa5,0x4d,0x86,0xed,0x85,0x98,0x34,0xdc,0xd2,0xcf,0xda,0x32,0x48,0xdb,0x24,
+0x3b,0x63,0x59,0x1d,0x50,0xa5,0x64,0x98,0x48,0x01,0xad,0x2a,0xcc,0xb7,0x6a,0xf4,
+0x43,0x1b,0x7f,0xe6,0xdb,0x19,0x67,0x96,0x63,0x00,0xcf,0xa5,0x5a,0x8f,0x55,0x29,
+0xd9,0x8e,0xd5,0xb8,0xcd,0x63,0xfd,0xd0,0xda,0x43,0xa2,0x7f,0x3b,0xa6,0x68,0xa3,
+0xf6,0x76,0x9a,0xbb,0x43,0x89,0x7c,0x2a,0x9f,0xa0,0x7e,0xc8,0xcb,0x61,0x7b,0xfb,
+0xe1,0xd5,0x09,0x5e,0x3f,0x7c,0xc8,0x75,0x76,0x79,0x51,0x7d,0x38,0xbc,0x36,0x8b,
+0xb9,0x2a,0x18,0xd4,0x19,0xf1,0x92,0x51,0xff,0xb3,0xb6,0x1d,0xae,0xb3,0x5e,0x68,
+0x76,0xb6,0xb3,0x56,0x0d,0xd0,0x3e,0x69,0x44,0x9e,0x84,0x4f,0xd9,0x74,0xe6,0x03,
+0x42,0xfc,0x70,0x68,0x25,0xc6,0xec,0xc7,0x16,0x12,0x65,0x48,0x3d,0xb8,0x6e,0xa5,
+0xd3,0x46,0xa1,0x29,0xa6,0xa6,0x71,0x6c,0x9a,0x93,0xc3,0x54,0xbe,0x04,0xe8,0x5b,
+0x97,0x59,0xc4,0x51,0x00,0xfb,0x5a,0xe3,0xd2,0xcb,0x9d,0x7b,0xb9,0x49,0x09,0x51,
+0xa8,0xfb,0x61,0x66,0xe9,0x2b,0xc2,0xe1,0xff,0x3c,0x5d,0x9d,0xc3,0x42,0x93,0xfc,
+0x10,0x7e,0xbb,0x5e,0xe2,0x52,0xec,0x86,0x05,0xe3,0x3c,0x83,0x3d,0xdb,0xb4,0x35,
+0x12,0x9e,0xa5,0xe4,0xfc,0x04,0x8e,0xc7,0x28,0xb3,0xb5,0x40,0x5a,0xcf,0x6c,0x0b,
+0x45,0x35,0xfb,0x61,0x1d,0x8a,0xaa,0x98,0x7f,0x25,0xec,0x85,0x97,0x43,0xe2,0x87,
+0x24,0x82,0xa0,0xd1,0xbc,0x4c,0xda,0x9c,0x09,0x87,0xb5,0xb4,0x97,0x9e,0x5c,0x4c,
+0x4b,0x88,0x43,0x1c,0x97,0x6e,0x7b,0x8a,0x4b,0xbb,0x56,0xfd,0xbf,0x6e,0xb3,0xf5,
+0x5e,0x55,0x0e,0x0b,0x74,0x5f,0x90,0xbf,0xf9,0xa3,0xa0,0x5f,0xdb,0xdd,0x0f,0xb1,
+0xab,0x79,0xe1,0xf0,0x7d,0xad,0x6e,0xb8,0x0e,0xbc,0x8f,0x9c,0x39,0x46,0x5b,0xa1,
+0xa2,0xd2,0x68,0xd4,0x54,0x2f,0x93,0xa9,0x5b,0xb0,0x33,0xd7,0x4a,0x1a,0x69,0x3d,
+0x91,0xab,0xd0,0xd9,0x0a,0x1c,0x5a,0xa2,0x5b,0xeb,0x31,0x93,0xf7,0x46,0xae,0xa7,
+0xf9,0xea,0x87,0x61,0x5c,0x3f,0xa4,0x7d,0xaa,0xa0,0x5f,0x15,0xb7,0x2d,0x17,0xf4,
+0x31,0x3b,0xe8,0xf9,0x6e,0xc7,0x78,0xbf,0x2d,0xab,0x2e,0x4c,0x67,0xb5,0xb8,0x76,
+0x32,0x4f,0x39,0xf4,0xe0,0x87,0xed,0x5d,0x3f,0x74,0xe2,0xb0,0x60,0xdb,0x50,0x69,
+0x8e,0x1f,0xe2,0xdf,0x58,0xde,0xb8,0xf4,0x76,0x0c,0xd7,0x0d,0x8d,0xd6,0x4d,0x19,
+0xb4,0x62,0xd0,0x36,0xff,0x12,0xad,0xf1,0x39,0xd6,0xc5,0xc8,0x59,0xea,0xe0,0x2b,
+0x7c,0xa5,0xe9,0x1c,0x7a,0x2c,0x5e,0xe2,0x52,0xd6,0xe2,0xca,0xfa,0x38,0x69,0x0b,
+0x17,0xee,0xc9,0x51,0xe6,0x24,0xbf,0xf3,0x21,0xce,0x8f,0xcd,0x49,0xc8,0x0d,0x53,
+0x12,0xae,0x1d,0xee,0x69,0x6e,0xc8,0xcf,0x61,0x49,0xd9,0x6f,0x1c,0x5a,0xbd,0x30,
+0xab,0x73,0xd1,0x68,0x3f,0x54,0x65,0x56,0xe7,0xe0,0xe5,0x10,0xb9,0x21,0x1b,0x73,
+0x09,0xfb,0xcc,0x20,0x49,0x74,0x0c,0x8b,0x51,0xfb,0x2b,0x99,0xfa,0xba,0x2d,0xf1,
+0xa9,0x29,0xaa,0xe3,0xa1,0xb1,0xe5,0x39,0x84,0xad,0x35,0x32,0xaf,0x1f,0xf6,0x62,
+0x0e,0xe9,0xc8,0x1f,0x93,0x27,0x1a,0xf1,0x07,0xfe,0x0c,0xd3,0xd2,0x67,0x3d,0x7c,
+0xdf,0x96,0x59,0x4f,0xf6,0x26,0xf2,0x59,0x9d,0xc3,0xef,0x48,0xac,0x95,0xc6,0x4b,
+0xfd,0x30,0xc2,0x39,0x52,0xb6,0x15,0xf5,0x9e,0xa5,0x9d,0xc6,0xd9,0x0b,0xeb,0xe7,
+0x87,0xc4,0xf7,0xac,0x7b,0xf3,0x2f,0xdd,0x0e,0xd7,0x2f,0x1d,0x71,0x43,0x58,0xd7,
+0xb3,0x78,0x9b,0xd9,0x03,0x2d,0x67,0xa4,0x63,0x3b,0xa3,0xe7,0x52,0x56,0xf8,0x5a,
+0xb4,0x5a,0xc3,0x0f,0xcb,0x1a,0x37,0xef,0x72,0xc4,0x91,0x5a,0xfd,0x50,0x2a,0xd1,
+0x7e,0x49,0xf6,0x39,0x19,0x7d,0x22,0x60,0xdc,0xcf,0x9c,0xec,0xcf,0x0f,0xd7,0x32,
+0x05,0x99,0xf9,0x61,0x42,0xf7,0x43,0x2f,0x71,0x69,0x41,0x4e,0xe4,0x7b,0xfc,0xbc,
+0x70,0x4b,0xc8,0xd9,0x0f,0x9d,0x48,0xec,0x0c,0xdc,0x0f,0x6f,0x52,0x3f,0x84,0xf4,
+0x59,0x2f,0xf3,0xd7,0x0f,0x51,0xbf,0xe1,0x3a,0xec,0x83,0x07,0xa3,0xd1,0x60,0xed,
+0xcf,0x5c,0x3f,0x82,0x6d,0x8f,0x41,0x94,0xe8,0xe6,0x09,0xae,0x39,0x62,0x88,0xc3,
+0x72,0x0b,0x70,0xc8,0x37,0xdf,0xa2,0x37,0x4c,0xfc,0x90,0x7d,0x7a,0x60,0x94,0x9c,
+0xc2,0xc6,0xab,0xa6,0x7d,0xc5,0xa5,0x1f,0x5f,0x42,0xe7,0x5a,0xda,0x14,0x97,0xee,
+0x78,0xac,0x1f,0xb6,0x3b,0x87,0x05,0x1b,0x7d,0x05,0x8b,0x17,0xa2,0x77,0xf9,0xaf,
+0x75,0xe9,0xb7,0x70,0xf2,0x3f,0xeb,0x58,0x8d,0xb2,0xb2,0xcd,0xe5,0x87,0xdb,0xb9,
+0x32,0xed,0x4f,0xb0,0xf5,0xb3,0x55,0x39,0x13,0x83,0x2c,0xd1,0xcd,0xc8,0xea,0xcb,
+0x5c,0x19,0x1c,0x5e,0xe5,0xf6,0xc3,0x60,0x8f,0xd0,0x5c,0x0a,0x32,0xef,0xdc,0xce,
+0x44,0xbe,0x6c,0xf9,0x4c,0x61,0x9c,0x41,0x3f,0x73,0x5f,0x7e,0xf8,0x91,0xe1,0x06,
+0x69,0x19,0x71,0x38,0x69,0x8a,0x4b,0x97,0x32,0x59,0xc7,0xb3,0xc4,0x56,0x94,0x76,
+0xe7,0xd0,0xdd,0x0b,0x11,0x1b,0x7c,0xb5,0x1e,0x2f,0xba,0x31,0xe8,0x14,0x95,0xb2,
+0x8d,0x5c,0xe2,0xf5,0xc3,0x87,0x7f,0x52,0xb6,0xcd,0xb1,0xa8,0xd6,0x27,0x33,0xa7,
+0x6d,0x7b,0xb9,0x81,0xb3,0x03,0xd3,0x27,0xa6,0x9f,0xab,0xb0,0x9d,0x70,0xd8,0x57,
+0xba,0xed,0xc4,0xf4,0x81,0xb3,0xfc,0xb3,0x34,0xf9,0xfc,0x10,0xc5,0x8d,0x07,0xce,
+0x7e,0x74,0xfa,0x81,0xa5,0xa0,0x5b,0x6e,0x4d,0xfc,0x60,0xec,0xea,0xc4,0xf9,0x89,
+0xab,0xda,0x5f,0x74,0x09,0x97,0x1f,0x4c,0xbc,0xa9,0x5f,0x46,0xb7,0xbc,0xa9,0x5d,
+0xfb,0x01,0xbe,0x4d,0xbf,0x55,0xdb,0xf4,0xff,0xbd,0x89,0x1e,0x83,0x1e,0x3b,0xd6,
+0xcf,0xcd,0x8c,0xc1,0xa1,0x62,0x89,0x1e,0x64,0x3a,0xc6,0xdd,0x88,0x4c,0x97,0x3d,
+0xfb,0xe1,0x8d,0xc1,0x65,0xc9,0xe0,0x50,0x22,0x1c,0xa2,0xf6,0x52,0x8f,0x1c,0xb6,
+0xb5,0x1f,0x7e,0x34,0x41,0xbc,0xcf,0x4a,0x9e,0xd5,0xa3,0xea,0xc0,0xe1,0x90,0x99,
+0x3a,0x73,0x44,0x4a,0x7a,0xe1,0xd1,0xb9,0xc8,0x57,0x3f,0x44,0xf3,0xfb,0x55,0x13,
+0x67,0x73,0xd2,0xb2,0x94,0x06,0x65,0xd2,0xf8,0x9e,0x61,0x09,0x7e,0x7e,0x33,0x9f,
+0x46,0x39,0x39,0x4c,0xb4,0x48,0xeb,0x03,0xf3,0x43,0xd3,0xe8,0x02,0xd9,0xda,0xf7,
+0x9a,0xf5,0xe8,0x87,0xc7,0xc2,0x11,0x7d,0xe4,0xaa,0xfe,0x8d,0x99,0x38,0xdc,0xd3,
+0x7b,0x0f,0x97,0xf4,0xb8,0xd4,0x9d,0xc4,0xf5,0x36,0xf7,0x43,0xd5,0xb1,0x75,0xc6,
+0x4a,0xa4,0xca,0xd9,0x0a,0xe8,0x45,0xb8,0x7e,0xc8,0x3e,0x61,0xf3,0xa8,0x61,0x83,
+0x45,0xc5,0x4b,0x3f,0xfe,0xb1,0xf0,0x5e,0xce,0xec,0x81,0x69,0x0b,0x89,0x8c,0x46,
+0x46,0xe4,0x8b,0x63,0x41,0xbf,0x33,0x1e,0x3d,0xd9,0x9b,0x6d,0x2b,0x0e,0x23,0x79,
+0x76,0xb4,0xd6,0x96,0x2d,0x32,0xfb,0x0a,0xed,0xb3,0x1e,0xfd,0xf0,0xe4,0x22,0xa1,
+0x30,0x2b,0x2f,0x83,0xb8,0x14,0xcf,0x7a,0x5a,0x32,0x38,0x74,0x2f,0xed,0x5d,0x3f,
+0xfc,0xe8,0x34,0xf4,0xc3,0x6a,0xef,0xb2,0x5e,0x71,0x29,0x8b,0x41,0x01,0x83,0xa6,
+0x11,0x68,0x65,0x0f,0xfd,0xf8,0x9f,0xc5,0x70,0x76,0xaf,0x2c,0xfd,0x66,0x71,0xb4,
+0x63,0x2f,0x84,0xc4,0xb4,0x94,0xca,0xf3,0x66,0x94,0x09,0x52,0x98,0xc3,0xb2,0xe2,
+0x96,0x8b,0xa6,0x55,0x38,0x4c,0x00,0x0e,0x61,0xad,0xd0,0x5a,0xbc,0xf9,0xe1,0x05,
+0x3a,0x5f,0x9b,0xfc,0x6e,0x42,0x3f,0xdc,0xc9,0x79,0xe0,0xb0,0xcd,0xfd,0xb0,0xba,
+0x0f,0x32,0xd7,0xaf,0x83,0x1f,0x0e,0x59,0x3d,0x90,0x5d,0x26,0x7d,0x52,0x38,0x32,
+0xe5,0x8d,0x4b,0x91,0xde,0x88,0x4f,0x4a,0x94,0x44,0x69,0x4e,0x23,0x71,0xce,0x95,
+0xc4,0x48,0x7e,0x34,0x1e,0xf4,0xbb,0x73,0x53,0xbb,0xf9,0xa1,0x89,0x43,0xa7,0x51,
+0xef,0xc6,0x75,0x2f,0x1c,0x3e,0x3b,0x42,0xe2,0x21,0xf2,0x7d,0xd9,0xfd,0x90,0xb4,
+0x97,0xba,0x45,0xa6,0xed,0xee,0x87,0xaa,0xab,0x17,0xa2,0x52,0xaa,0x93,0x1f,0xda,
+0x0b,0xf4,0x42,0x3c,0x62,0x9b,0xbf,0x7e,0x88,0x15,0x1e,0x49,0x4b,0xd0,0x13,0xd3,
+0x5a,0xd1,0xa2,0xd3,0x0a,0x34,0xa2,0x32,0x27,0xed,0xe5,0x1a,0x9d,0x81,0xaf,0xdd,
+0xfc,0x30,0x62,0xf7,0x43,0x4b,0x51,0x3d,0xfa,0x21,0xca,0x51,0xc6,0xe6,0xf8,0x5b,
+0xeb,0x87,0x11,0x54,0x3f,0x34,0xfc,0xb0,0x04,0xe6,0xb1,0x15,0x4c,0xfb,0xfd,0xe3,
+0x87,0x2a,0x47,0x54,0x5a,0x9f,0xb8,0xf4,0xe6,0x20,0x1b,0xf3,0xa2,0xca,0x6c,0x4e,
+0x04,0x99,0x49,0x63,0xf4,0x04,0x7a,0xe6,0x10,0xcd,0x22,0xc9,0xb2,0xdf,0x58,0x19,
+0x79,0xa2,0xe6,0x8c,0xd2,0x5c,0x45,0x0e,0xd3,0x52,0x56,0xf6,0x93,0x13,0xae,0x16,
+0x11,0x3f,0xac,0xbe,0xb5,0x0e,0x87,0x0e,0x71,0xa9,0xd9,0x0b,0x8d,0x1e,0x7e,0x7e,
+0x0e,0xd7,0x32,0x6c,0x9e,0x28,0xeb,0xb7,0xd0,0x7b,0x10,0x8d,0xf6,0xd2,0x6d,0x4b,
+0x7b,0x69,0x65,0x0a,0xd1,0xd9,0xd3,0xce,0x1c,0x62,0x3f,0x74,0x2f,0xa5,0x3a,0xc4,
+0xa5,0x37,0x06,0xc9,0xa8,0xe3,0x02,0xd8,0xc8,0xa8,0x6b,0x95,0xfc,0xc6,0xfa,0xe0,
+0x30,0x14,0x3a,0x70,0x16,0x44,0x3b,0xa0,0xae,0xa8,0x45,0x3e,0xda,0xaf,0xae,0x5e,
+0x67,0x94,0x97,0x2d,0x24,0x9e,0x0c,0x7c,0xc4,0x50,0x35,0x3d,0xd9,0x5b,0x90,0x79,
+0x7a,0xf8,0x5a,0x9e,0x43,0x9f,0xf5,0xc3,0x8f,0x2f,0x95,0xf5,0x39,0xa0,0x25,0x53,
+0x64,0x8a,0xfd,0x90,0xce,0x3f,0x34,0x38,0x24,0x23,0xf5,0x59,0x5f,0x96,0xfd,0xac,
+0x2d,0xed,0x0b,0x3f,0x74,0x2b,0x75,0x69,0x2f,0x1d,0x22,0xb3,0x93,0x58,0xdf,0x7d,
+0x09,0x90,0xb8,0x6e,0xfc,0xca,0x6a,0x1c,0xfa,0xf0,0xaa,0x6b,0xd3,0x15,0x7a,0x0f,
+0x25,0x1c,0x01,0x2d,0xeb,0xf1,0x2a,0x6e,0xa3,0x4b,0xeb,0x51,0x6b,0xb6,0x0e,0x9e,
+0x5f,0x59,0x24,0x2e,0xb5,0xfa,0x5f,0xdb,0xf9,0xa1,0xc5,0x1b,0xf9,0x38,0xbc,0x35,
+0x51,0x02,0xd1,0x26,0xe5,0xd0,0xd2,0x6f,0xc1,0xfc,0x90,0xdd,0xaf,0x12,0x89,0x88,
+0xc3,0xf6,0x5d,0x03,0x03,0xb7,0x97,0x36,0x87,0x43,0xec,0x87,0xa4,0x55,0xc6,0x9a,
+0x7f,0x8c,0xd5,0xfd,0xfd,0xf8,0x21,0xd2,0xc3,0x4b,0xaa,0xcd,0x13,0xdd,0x0a,0xdf,
+0x98,0xb4,0x20,0xc4,0x38,0xdc,0x4f,0x7e,0x58,0xe6,0xe2,0x70,0x34,0xbe,0x2c,0x91,
+0x59,0x54,0xeb,0x0e,0xed,0xa5,0x6c,0x3e,0x3e,0x6e,0xa7,0x51,0x8d,0xd9,0xc7,0xac,
+0x3f,0xab,0x60,0x21,0xb3,0x10,0x58,0x86,0xaa,0xe6,0xe8,0xbd,0x26,0x72,0x78,0x77,
+0xa8,0xa4,0x90,0xb9,0xf1,0xfa,0xa7,0x4b,0x32,0x31,0x19,0x3c,0x92,0x99,0x72,0x5e,
+0xfa,0x2d,0xcc,0x82,0x7d,0x53,0xbc,0xc5,0x5f,0x0e,0x7f,0xef,0xda,0x9f,0x1c,0xf2,
+0xf9,0xe1,0x5e,0xae,0x44,0x5b,0xe1,0xa0,0x23,0x2e,0x1b,0xf5,0x43,0xd6,0x6f,0xb1,
+0x46,0x39,0x84,0xfe,0xa7,0x82,0x3d,0xbb,0xdc,0xce,0x1c,0x6a,0x7e,0x58,0x31,0xdf,
+0xae,0xd9,0xf5,0x83,0xe7,0x30,0x3c,0x52,0x06,0xf5,0x7b,0xcb,0xdc,0x5b,0x30,0x6e,
+0xc3,0xaf,0x1f,0x22,0xad,0x65,0x2a,0xe5,0x13,0xce,0x56,0xdc,0x1a,0xb3,0x56,0x02,
+0x1f,0x87,0xd1,0xcd,0x76,0xe3,0xb0,0x20,0x9f,0x73,0xe9,0x03,0xea,0x5c,0x28,0x93,
+0x3c,0x40,0xfa,0x77,0xec,0xe0,0x87,0x92,0x39,0x3f,0x0d,0x9d,0xe7,0xa8,0xc7,0x4d,
+0xe6,0xe8,0x94,0xd5,0x68,0x82,0xcb,0x24,0xde,0x78,0x35,0xb3,0x9d,0xe6,0xf3,0x63,
+0x65,0x45,0xa5,0x7d,0x84,0xd0,0x0d,0xcd,0x33,0x77,0xfd,0xd5,0x0f,0xb1,0x8e,0x85,
+0xbb,0x56,0x2b,0x67,0xf6,0x76,0x2e,0x69,0xe9,0x66,0x03,0xfa,0xf5,0xf7,0xab,0x1f,
+0xba,0x71,0xf8,0x8b,0x97,0xf5,0xef,0x83,0xcd,0xda,0x00,0xbf,0x8c,0x59,0x09,0xf8,
+0x61,0x9e,0xf5,0xe3,0xab,0x8a,0xd5,0xfb,0xec,0xfe,0x18,0x4c,0xc6,0xc6,0x66,0xe9,
+0xa3,0xd3,0xeb,0x7c,0x1c,0xd6,0xa1,0x0d,0x43,0xf7,0x43,0x3d,0x1e,0x65,0xe3,0xf5,
+0xa1,0x3b,0xb2,0x3a,0x87,0x7f,0x3f,0x44,0xe7,0x7b,0x2a,0x0f,0xbf,0x6d,0xf7,0x82,
+0x6a,0x1a,0xdf,0xae,0xfb,0x1a,0x7b,0xfd,0xfb,0xd2,0x0f,0xcb,0x2e,0x1c,0xde,0x1d,
+0xca,0x1a,0xd4,0xd0,0xb9,0xda,0xa6,0x1e,0x44,0x36,0xd2,0x9b,0xcd,0xb8,0x30,0xfc,
+0xd0,0xe8,0xd5,0x2a,0x80,0x36,0x56,0xc2,0x60,0xc1,0xf0,0xc3,0x76,0xe6,0xb0,0xb9,
+0x7e,0x68,0xd4,0x11,0x2a,0xcf,0xdc,0xad,0xa1,0x9d,0x86,0xe8,0xc6,0x60,0x5a,0x32,
+0xaf,0xcd,0xe0,0x48,0x9f,0xe9,0xdd,0x46,0xf2,0xc1,0xae,0xe3,0x67,0x17,0x5f,0xbf,
+0x45,0xbb,0x71,0x58,0xdd,0x0f,0xf5,0x31,0xdd,0xc6,0xef,0x3a,0xf1,0x42,0xc6,0x14,
+0xe3,0x90,0xb4,0xd3,0xa0,0xf5,0x26,0xdf,0x5e,0x9c,0x93,0xf0,0x4c,0x63,0xdc,0xcb,
+0x51,0xa0,0xbd,0x18,0x05,0xd3,0x5f,0x35,0xa0,0x8c,0xfe,0xcd,0xd1,0x47,0xa7,0x4b,
+0x4d,0xe3,0x10,0xd7,0x0f,0x4b,0xf6,0xb9,0xf0,0x81,0xfa,0x21,0x52,0x7c,0xac,0x40,
+0xda,0x61,0x61,0xcf,0x88,0xac,0x82,0xd7,0x53,0x69,0x24,0x8c,0x57,0x8b,0xa9,0xf5,
+0x35,0xdd,0xd4,0x9e,0x1c,0x5a,0x37,0x6f,0x7e,0x88,0xdb,0xcd,0x90,0xa7,0xb1,0x56,
+0x80,0x6a,0x1c,0x22,0x3f,0x7c,0xef,0xb4,0x9e,0x29,0x8e,0x66,0x2f,0x21,0x59,0x4f,
+0xd6,0x49,0x1d,0x13,0xd4,0x0f,0xdb,0xd7,0x0f,0x1f,0x34,0xdb,0x0f,0xe9,0x0a,0x2d,
+0xd6,0x99,0xbb,0xac,0xcd,0x26,0x08,0x26,0xde,0x3b,0xcd,0xbe,0x77,0xab,0xdf,0x96,
+0x40,0xae,0x79,0x7a,0x8b,0x12,0xec,0x8a,0x9a,0x76,0xf1,0xd6,0x0f,0x97,0x65,0x34,
+0xaf,0x71,0xa0,0xa6,0x72,0x61,0xfa,0x8f,0x67,0xaf,0xcd,0x9e,0x98,0xbe,0x5f,0x43,
+0xbd,0x17,0x71,0x58,0x89,0x3e,0x3e,0x3f,0x3c,0x31,0xcd,0x62,0x8f,0x12,0xc8,0x57,
+0x59,0x99,0xc3,0xbd,0xdc,0x73,0xd3,0x21,0x96,0xb1,0x11,0x52,0x08,0x47,0x42,0xe2,
+0x7d,0x5b,0x73,0x38,0x70,0xb6,0xb9,0x7e,0xc8,0x97,0x79,0x29,0x08,0x6f,0x7a,0x6e,
+0x9a,0x2f,0xae,0x82,0xaf,0x1b,0x7c,0xee,0x64,0x26,0xde,0xf1,0x34,0x65,0x25,0x56,
+0x8c,0x15,0xa3,0xda,0x16,0xdb,0x44,0x7b,0x54,0x62,0x9b,0x64,0x8f,0x2e,0x19,0xff,
+0xdf,0x8c,0x19,0x1b,0xbe,0x45,0xbf,0xb6,0x19,0x2b,0xd2,0x47,0x6b,0xa5,0xac,0x1c,
+0x38,0xeb,0xf7,0x78,0x9d,0xfd,0xb0,0x4c,0x3f,0x2b,0x37,0x3f,0x7c,0x76,0x24,0x4b,
+0x29,0x5c,0x67,0x9f,0x32,0xed,0x1b,0xc4,0x1c,0x2e,0x83,0xfa,0x61,0x64,0x15,0xaf,
+0x31,0x06,0x33,0x72,0xc0,0xac,0x96,0x2c,0x1b,0xd8,0x7a,0xdb,0xfb,0x61,0xb3,0x39,
+0x04,0x3e,0x58,0x31,0x8b,0x45,0x50,0x31,0xe2,0x4f,0x2f,0x79,0x27,0xb1,0x7e,0xfd,
+0xfa,0xbc,0x7e,0x18,0x64,0x89,0x6e,0x4e,0x4a,0x7e,0x8f,0x37,0x02,0xfc,0xd0,0x4a,
+0x21,0xfc,0xc4,0x9c,0x39,0xbc,0x6d,0xcc,0x47,0x03,0x7e,0xa8,0x90,0x98,0x07,0xf6,
+0xe4,0xe3,0xcc,0x18,0xb8,0xdf,0x62,0x27,0x87,0x66,0xc1,0x90,0x4c,0x71,0xec,0x3c,
+0x61,0x6b,0x54,0x92,0x3a,0x26,0xae,0x67,0xb6,0x73,0xfd,0x10,0xae,0x5e,0xdd,0xb4,
+0xfa,0x61,0x43,0xfc,0x10,0xc9,0xbc,0xc6,0x3b,0xcf,0x2b,0x97,0x95,0x5b,0x75,0x9a,
+0xaf,0xdf,0xaf,0xf9,0x61,0x74,0xb3,0xd1,0x24,0x4e,0x72,0xad,0xfe,0xeb,0xa4,0x48,
+0xde,0x7c,0xb4,0x25,0xb0,0x87,0x9b,0x33,0x87,0x33,0x8b,0xb8,0x7f,0x10,0x9f,0x4d,
+0xeb,0x96,0xfc,0xe2,0xe4,0x2c,0xa3,0x33,0x81,0xf5,0xb8,0x14,0x67,0x4a,0x60,0x19,
+0xaa,0x48,0x46,0x76,0x32,0xd2,0x83,0x8c,0xc1,0x22,0x44,0xb6,0xb3,0x1f,0x1e,0xe0,
+0xe7,0x30,0xf0,0x55,0x8f,0x0d,0x0e,0xad,0xf3,0xba,0xeb,0xc8,0x21,0xca,0x9c,0xe1,
+0x95,0x44,0xb5,0x4e,0xfd,0xfa,0x7c,0xfd,0x16,0xc1,0x73,0xd8,0xeb,0x97,0xc3,0x55,
+0x48,0xa0,0xf3,0x66,0x70,0x38,0x68,0x7d,0x2c,0xca,0xd3,0xbd,0x2c,0x65,0xe9,0xd9,
+0x04,0xfd,0x50,0xa5,0xa3,0x4c,0xf1,0xdc,0x18,0xcc,0xe1,0xa4,0x44,0x56,0xd9,0xee,
+0x21,0x71,0x29,0x65,0xd0,0xc8,0xc2,0x67,0x59,0x97,0xb2,0xbd,0xfb,0xf1,0xf9,0xfd,
+0xf0,0xa7,0xfb,0xc0,0x0f,0x91,0xf6,0x72,0x5e,0x49,0xcc,0xca,0x37,0x6c,0x67,0x56,
+0xed,0xea,0xe7,0xae,0x1f,0x06,0x57,0x50,0x5c,0xea,0x9b,0xc3,0x7c,0xe5,0xe7,0x85,
+0x34,0xda,0xfd,0xf0,0xfc,0x18,0x9e,0xcf,0xc2,0xfc,0xd0,0xfa,0x19,0xb3,0x1a,0x22,
+0xc9,0xd8,0xc6,0x66,0xa1,0x19,0x7e,0x08,0x1f,0x43,0xf3,0x3e,0x93,0x99,0x39,0xeb,
+0x35,0x65,0x30,0x6e,0x05,0xf1,0xfb,0xe1,0x4f,0xeb,0xe5,0x87,0x0d,0xe6,0xf0,0x72,
+0x27,0x6f,0x4f,0x18,0x7b,0xfd,0xc9,0x3a,0x7c,0xc3,0x4f,0x36,0x29,0x2e,0xf5,0xcf,
+0xa1,0xd3,0xd1,0x96,0x2c,0x24,0x22,0x0e,0x5f,0x35,0x71,0xd8,0xdf,0x1b,0xc9,0xeb,
+0x1c,0x42,0x3f,0x24,0xfc,0x19,0x54,0x59,0xfd,0x30,0x91,0x7f,0x95,0xfe,0xf2,0xf5,
+0x84,0xbf,0xa3,0x7f,0x5f,0xa6,0x7e,0x65,0x99,0xf4,0x35,0xad,0x83,0xf6,0x1b,0xff,
+0x19,0xfd,0x9b,0xaf,0x6a,0x7e,0xa8,0x9a,0x39,0x6c,0x9a,0x1f,0x46,0x37,0x83,0xed,
+0xcb,0xeb,0xef,0x4d,0x4b,0x5e,0x49,0x8c,0x04,0x3e,0xa7,0x46,0x6f,0x2f,0xbd,0xd3,
+0x68,0x0e,0xf9,0xb2,0xe8,0x3b,0xc9,0x99,0x43,0x7b,0xb1,0xfa,0xe1,0x4c,0x06,0x67,
+0x20,0x49,0x03,0x0e,0x2d,0xf5,0x0f,0x7a,0x3b,0x19,0xe9,0xfd,0x11,0x18,0x6b,0xdf,
+0x1b,0x9e,0x34,0x7e,0x37,0x55,0xab,0x8f,0x9a,0xfb,0xbc,0x7c,0x64,0x6c,0x6c,0x1d,
+0x0d,0x9c,0x55,0x5d,0xfc,0x50,0x35,0xe2,0xf9,0xf7,0xf7,0x89,0x1f,0x22,0xa1,0xd1,
+0x55,0x5e,0x49,0xf4,0xb6,0x36,0xb8,0xbb,0x9a,0xe3,0x87,0x73,0xf2,0xbb,0xbe,0x39,
+0x74,0xfb,0xd5,0x28,0xe9,0x7f,0x55,0xf9,0x55,0x10,0xc5,0x5f,0x9b,0x9d,0x34,0x72,
+0x00,0x2d,0x83,0x79,0xae,0xd6,0x4f,0x97,0x71,0x98,0xb5,0xcd,0x02,0xd5,0x38,0x94,
+0x88,0x1f,0x9a,0x0b,0x5b,0xcf,0xd1,0xf0,0x43,0x9f,0x19,0xfd,0x5b,0x41,0x95,0xfc,
+0x50,0x05,0x5b,0xb3,0xfd,0xb0,0x1e,0x63,0x5b,0x5e,0x1c,0x53,0x3d,0x93,0x78,0x24,
+0xd0,0xf9,0xfa,0xa8,0x7e,0xf8,0xe5,0x9d,0xc6,0x92,0x18,0xdb,0xcc,0xca,0x3c,0xab,
+0x59,0x38,0x89,0xd7,0x0f,0x55,0xe0,0x87,0xb7,0x26,0xd0,0x88,0x6d,0xcc,0x61,0x1a,
+0x72,0x68,0x62,0x0a,0xb5,0xb6,0x50,0x0e,0x65,0xfb,0x77,0x6d,0xcd,0x50,0x45,0xd7,
+0xd8,0x80,0xb3,0x74,0xe4,0x76,0xf7,0xc3,0x6a,0xf5,0x43,0x16,0x99,0xee,0x2f,0x3f,
+0x44,0x7a,0x70,0xba,0xa4,0x78,0x25,0x31,0xc8,0xcf,0xa0,0x19,0xfd,0x16,0xd1,0x9a,
+0x38,0xe4,0x7b,0x0d,0xc6,0xe1,0xb9,0xf8,0x5e,0x8e,0x71,0x08,0xfd,0xd0,0xea,0x6d,
+0xec,0x3c,0x9b,0x94,0xde,0xb0,0xb5,0x89,0x45,0x4c,0x99,0xc4,0x1d,0x56,0x87,0xad,
+0x71,0x85,0x9b,0x56,0x90,0x5b,0x7b,0xa9,0x4a,0x3f,0xb7,0xc6,0xfb,0x61,0x99,0x6e,
+0xf5,0x19,0xeb,0x79,0x62,0xba,0xec,0x89,0x44,0x74,0x6f,0xff,0xe3,0x51,0xac,0x62,
+0x71,0x29,0xfa,0x5b,0x69,0x83,0xff,0x37,0x13,0x55,0x8d,0xb6,0x4a,0xff,0x89,0x15,
+0x6b,0xe1,0x30,0xc6,0xf5,0xab,0x51,0x52,0x30,0x49,0x3d,0xa1,0x99,0xc5,0x48,0x3e,
+0x42,0x39,0x9c,0xb3,0xf5,0xe2,0x3b,0x91,0xf8,0xc0,0x61,0x16,0xb6,0x53,0xbb,0x9a,
+0xea,0xb0,0xf7,0x9a,0x49,0xbc,0x95,0x54,0x99,0x43,0x15,0xec,0xd1,0x27,0xb7,0xd5,
+0x24,0x3f,0x44,0xdf,0x6d,0xbd,0x56,0x98,0xfc,0xd8,0xe3,0x08,0x1b,0x74,0xef,0x37,
+0x03,0xea,0xd7,0x77,0xf2,0x43,0x2b,0x81,0xd5,0xa8,0xf2,0xe3,0xa5,0xba,0x1f,0xd6,
+0xad,0x7e,0x48,0x0a,0xce,0xca,0x7c,0x6d,0x16,0x8d,0x0f,0x65,0x1c,0x92,0xf6,0x52,
+0xd5,0xda,0x4a,0x43,0x29,0x54,0x15,0xe7,0xb5,0xfd,0xec,0x19,0x1b,0x4d,0xbe,0x48,
+0xe7,0xa9,0xee,0x37,0x3f,0xc4,0xe4,0xa9,0xa6,0x4b,0x65,0xe5,0x5a,0x43,0x39,0x2c,
+0x83,0x2d,0xe8,0xf6,0x52,0xa8,0xdf,0xf7,0x3c,0xc2,0xa6,0x20,0x7f,0x7e,0x2c,0x88,
+0x57,0xd6,0x39,0x2c,0x22,0x36,0x98,0x2b,0xb2,0x3d,0xb9,0xd5,0x8d,0x40,0xab,0x6f,
+0x56,0xa7,0xb5,0x36,0x3f,0x44,0x47,0xcb,0x53,0xd0,0x2c,0xea,0x5b,0x13,0x3b,0x1a,
+0x85,0x7b,0x3f,0x01,0x1c,0x56,0xf1,0x43,0x55,0xaf,0xf9,0x54,0xfa,0xb5,0x0d,0x36,
+0x43,0x55,0x6b,0xaa,0xba,0x1f,0xaa,0xa0,0x9d,0xa6,0x91,0x1c,0x96,0x4d,0x5b,0xfd,
+0xfc,0x10,0xc9,0x75,0x84,0x8d,0x6c,0x3d,0xb6,0xb4,0xe4,0x96,0xf9,0x81,0x47,0xc4,
+0x0f,0x2b,0x79,0x9f,0x9b,0x0f,0x56,0x8b,0x56,0x2b,0x91,0x59,0x9b,0x1f,0xf2,0x3a,
+0xf0,0xb9,0xf8,0x68,0x7c,0x29,0xb3,0x9d,0xdb,0xc9,0x75,0xad,0x46,0xf2,0xa9,0x3c,
+0xe9,0xb5,0x20,0x1c,0xda,0x57,0x44,0x47,0xed,0x9d,0x59,0xd9,0x5e,0x33,0xc4,0xaa,
+0xce,0x21,0x6d,0xb5,0xd9,0x17,0x1c,0xc2,0x28,0xd4,0x3a,0x57,0x16,0x7d,0x4a,0x8d,
+0xf0,0xc3,0xb2,0x6d,0x23,0x67,0x4f,0x7d,0x57,0x3e,0x47,0x23,0x6c,0x54,0xf8,0xad,
+0x42,0xfa,0xc0,0x08,0x74,0x32,0x26,0x12,0xe5,0xaa,0xf0,0x7b,0x36,0x33,0x21,0x0e,
+0x63,0x45,0xe4,0x7b,0x66,0xef,0xc3,0x7c,0x91,0x5b,0x19,0x51,0xe6,0x4b,0xec,0x51,
+0xe4,0xbe,0xec,0x39,0x9c,0xa2,0xdb,0x40,0xfc,0x90,0xb3,0x7e,0xf8,0xe6,0xd8,0xc3,
+0x3f,0x59,0xcb,0x6c,0x67,0xf6,0x34,0x0e,0x71,0x3b,0x0d,0xec,0x3d,0x54,0x6d,0x14,
+0xe2,0xf2,0x8b,0x97,0x2b,0xbd,0x72,0xd0,0x99,0x53,0x5b,0x51,0x66,0x3f,0x54,0x4d,
+0x44,0xaa,0x32,0x6c,0xa7,0x69,0x94,0x1f,0xda,0x49,0xac,0x37,0x87,0xef,0x74,0x26,
+0xf2,0x24,0x77,0x18,0x9c,0x61,0xba,0x2e,0x93,0x39,0xe0,0xe6,0xb9,0x6f,0xfe,0x32,
+0x1b,0x5b,0x45,0x38,0x34,0x93,0x67,0xa6,0xcf,0x28,0x77,0x50,0x8f,0x03,0xbe,0x1d,
+0xed,0x71,0x6f,0x07,0xde,0x7f,0x69,0xec,0xd1,0x33,0xe9,0xd7,0xb5,0x2d,0x8a,0x9e,
+0xf5,0x0e,0x7e,0x2e,0x74,0x7f,0x14,0x4f,0x7e,0xa9,0x3f,0x53,0xb2,0xe8,0x7f,0x56,
+0x31,0x7f,0x5c,0x7a,0x72,0x71,0x66,0x71,0xc9,0xe0,0xd0,0xee,0x87,0x4e,0x1c,0x96,
+0x2b,0xd4,0x0c,0xb1,0x78,0x39,0xdc,0x2f,0xf5,0x43,0xd5,0x46,0x23,0x99,0x6d,0x59,
+0xaa,0x9b,0x1f,0x3a,0x7b,0x60,0xc9,0xf4,0xbd,0x46,0x37,0x83,0xee,0x43,0xb7,0xea,
+0xdb,0x71,0xbc,0xd2,0x02,0xac,0x19,0xc3,0x4c,0x44,0x2a,0xfc,0x6c,0xd0,0x4a,0x70,
+0x1a,0x89,0x33,0x35,0xce,0x12,0xa6,0x7e,0xa8,0x53,0x82,0xc8,0x31,0x68,0xbb,0x43,
+0xae,0x1b,0x54,0x12,0xca,0x14,0xbc,0xb7,0xff,0x66,0x95,0xe9,0x65,0xf2,0xd7,0xb9,
+0xa0,0x51,0x6d,0xfe,0x57,0xb6,0xe2,0x6d,0x2f,0x45,0x23,0x1e,0x4e,0x2e,0xae,0x65,
+0x76,0x8c,0x56,0x1a,0xb3,0x1f,0x3a,0xb5,0x95,0xa2,0xd1,0x4a,0xd5,0x5e,0x99,0xdf,
+0x0f,0xbf,0xdd,0xf0,0xd5,0x82,0x82,0x12,0xe3,0x10,0xb6,0xcb,0x80,0xcb,0xd4,0x27,
+0xea,0xc1,0x21,0x39,0xab,0xec,0x34,0x42,0x12,0xbf,0xbc,0x53,0xff,0xb5,0x27,0xee,
+0x0e,0xa5,0x25,0xbe,0x99,0x98,0xa4,0xd4,0x3a,0x4b,0x98,0xf9,0x21,0xf1,0xac,0xd8,
+0x26,0xf3,0x30,0x42,0x23,0x8a,0x24,0x9f,0x1d,0xb9,0x31,0x78,0x77,0xe8,0xe6,0xd0,
+0x5d,0xad,0xdc,0x18,0x3c,0x17,0x7f,0xd5,0xfb,0x36,0x88,0xf6,0xb5,0xd5,0x6a,0x35,
+0x0e,0x39,0xfd,0x70,0x2d,0x83,0xfc,0x10,0x71,0xd8,0xa5,0x51,0x88,0xfd,0x70,0x4e,
+0x66,0x7e,0x68,0xa5,0xb0,0x72,0xcd,0x10,0x2b,0xb8,0x8c,0x8d,0xad,0xab,0x81,0xe9,
+0x12,0xc8,0x6a,0x4f,0x09,0x04,0xd1,0x18,0x1e,0x53,0x5b,0x1f,0x3f,0x44,0x67,0xa1,
+0x13,0x79,0xe6,0x12,0xdb,0x6c,0xc4,0x1a,0x30,0x2f,0x8e,0x65,0x3d,0x71,0x88,0xda,
+0xae,0x6a,0x99,0x25,0x4c,0x39,0x04,0x51,0x25,0x2a,0x24,0xd2,0xd4,0xa3,0x4d,0xed,
+0x3f,0x69,0xdf,0x33,0x77,0x83,0x95,0x37,0x0e,0x99,0x1f,0x9a,0x7b,0xf1,0x09,0x85,
+0xf0,0x3b,0xaf,0x5c,0x33,0xc4,0xfa,0x4a,0x70,0xe8,0x50,0x3f,0x54,0xc1,0x65,0xe2,
+0x89,0xf5,0x6b,0xa7,0x71,0x27,0xb1,0x31,0x1c,0xa2,0x1c,0x36,0xbc,0x39,0xbf,0xd9,
+0xcc,0x72,0xff,0xb3,0x84,0x75,0x0e,0x71,0x5d,0x8f,0x52,0x87,0xeb,0x76,0xa4,0xde,
+0x87,0x09,0x4d,0xfb,0x9e,0x21,0x11,0xac,0xfc,0x72,0x88,0xfd,0x30,0x6b,0xf3,0x43,
+0x12,0x47,0xbb,0x8f,0x16,0xe4,0xe0,0x50,0xde,0x3f,0x1c,0xb2,0x98,0x14,0x64,0xba,
+0x97,0x4b,0xc6,0x0c,0xaf,0xfa,0xf9,0xa1,0x7b,0x69,0x14,0x87,0xa1,0xd0,0x73,0x67,
+0xf1,0xdc,0x1b,0xd4,0xe7,0xac,0xaf,0xd5,0x86,0xb7,0xaa,0x3c,0xfa,0x9d,0x25,0xdc,
+0xdf,0xab,0xca,0x46,0x46,0x99,0x22,0xc9,0x3b,0x13,0x65,0xd7,0x8d,0x08,0x15,0x71,
+0xd8,0x1a,0xab,0xa7,0xec,0xe5,0x78,0x39,0xdc,0x76,0xf0,0x43,0x6b,0x2b,0x0d,0xb9,
+0x6f,0xf5,0x9a,0x21,0x16,0xc9,0x50,0xb5,0xff,0xfd,0xd0,0xdc,0x46,0x6a,0xac,0xfa,
+0xc2,0x5a,0x2c,0xea,0xec,0x87,0x6e,0x25,0x5a,0x6c,0xdc,0xda,0x84,0xd7,0x66,0x97,
+0xab,0xac,0x57,0x4a,0x56,0x2d,0x45,0xdb,0x32,0x5a,0x6b,0x58,0x3b,0xbf,0x26,0x25,
+0x7f,0xb3,0x84,0x71,0x5c,0x6a,0xb4,0x75,0x6a,0x7b,0x56,0x4b,0x04,0xad,0x32,0xc5,
+0xd6,0xf1,0x43,0x7e,0x0e,0x9d,0xe2,0x52,0xd8,0x7b,0x58,0xa2,0x24,0x16,0x5c,0x6a,
+0x86,0x58,0x5f,0xa5,0xb8,0xd4,0x58,0x7b,0x47,0x06,0x59,0xee,0xe9,0x1a,0x84,0xf8,
+0x53,0x6b,0xa2,0x1f,0x36,0x90,0x43,0x34,0xd6,0x0d,0xcf,0x08,0x67,0x25,0x6d,0xb9,
+0x6c,0x5d,0xc1,0x34,0x92,0xf7,0xd3,0x5e,0x8e,0xfd,0xd0,0xc8,0xbe,0xb6,0x49,0x73,
+0xaa,0x6d,0x46,0x8b,0xe6,0x1c,0x6c,0xad,0xe7,0x87,0xce,0x7d,0x93,0x95,0xfd,0xd0,
+0xdc,0x6b,0xc1,0x28,0x2c,0x2b,0x4e,0xa3,0x49,0xed,0x72,0xca,0x50,0xb5,0xdf,0x38,
+0x3c,0x31,0xcd,0x56,0xdd,0x21,0x5e,0xb8,0x6e,0x78,0x60,0x41,0x61,0x79,0x77,0xeb,
+0xd7,0x6f,0xd1,0x6a,0x1c,0xa2,0x75,0x50,0xf0,0x0a,0x0b,0xac,0xa4,0xf4,0x0d,0x95,
+0xef,0x48,0x29,0x0b,0xa3,0xe8,0x1c,0xdb,0xce,0x78,0x67,0x05,0xfb,0x21,0x26,0x0f,
+0x70,0x08,0x32,0x24,0xe2,0xeb,0xad,0xe4,0x87,0x7c,0xbf,0x9b,0x3b,0xb9,0xaa,0x71,
+0xa9,0x41,0x62,0xb4,0x58,0xad,0xcf,0x10,0xaa,0x6b,0xb5,0x1a,0x7d,0xac,0x64,0xdb,
+0x98,0xc3,0x6b,0xb3,0x6c,0x1d,0x3a,0x90,0xeb,0x1a,0xac,0x3e,0x50,0x4f,0x3f,0xfc,
+0x92,0x8b,0xc3,0x46,0xc6,0xa5,0x58,0x27,0x17,0xf5,0xfc,0x99,0xa0,0x24,0xe8,0x06,
+0xe9,0x24,0x4c,0xce,0xc9,0xde,0x7b,0x13,0x8d,0xfa,0x21,0xa1,0xcf,0x20,0x8f,0xee,
+0x8d,0xdb,0x93,0x2d,0xe6,0x87,0x6e,0x5e,0x88,0xfe,0xb7,0x9d,0x9b,0xc9,0x6c,0x67,
+0x76,0xf4,0xd1,0x34,0x46,0xaf,0x85,0xad,0x7e,0x18,0xdd,0xe4,0xa9,0x19,0x62,0x75,
+0xd1,0x19,0x57,0x95,0x3d,0x11,0x9d,0xaf,0xed,0xec,0x87,0xd7,0x66,0xcb,0x0a,0x71,
+0x43,0x98,0x03,0xcb,0xe0,0xd0,0x88,0xe6,0xeb,0x55,0x3f,0xe4,0x8d,0x4b,0xeb,0xdd,
+0x8f,0x6f,0xd5,0xcb,0x61,0x34,0x67,0x07,0xcd,0x17,0xc0,0xa5,0x6b,0x75,0xef,0x27,
+0x68,0x3d,0x3e,0x34,0x3e,0x24,0xb2,0x0a,0xc9,0x24,0x44,0xa6,0x25,0xaf,0xbd,0x89,
+0x26,0x0e,0x37,0x0d,0x02,0x89,0x0f,0x92,0xc8,0xb4,0xc5,0xe2,0xd2,0x6a,0x23,0xca,
+0xa1,0x1f,0xbe,0xad,0xf9,0xe1,0x9e,0x63,0x5c,0x8a,0x33,0x26,0xea,0x59,0x6c,0xb8,
+0x6b,0xd5,0x11,0xae,0x8c,0xfe,0xaa,0xdc,0xfe,0x7e,0xa8,0x52,0x3f,0x34,0xd6,0x5f,
+0x32,0x65,0xf7,0x55,0xeb,0x57,0x3f,0xe4,0xaa,0xf9,0x37,0x3a,0x2e,0x45,0xfa,0x34,
+0xf6,0x5a,0x06,0xad,0xaf,0x40,0xca,0x1e,0xdd,0x20,0x9d,0x11,0xca,0x22,0xfa,0xdd,
+0xf7,0xd6,0x9b,0xc8,0x38,0x8c,0x3a,0x44,0xa3,0xb1,0x16,0xf4,0xc3,0x64,0x11,0x8e,
+0x68,0x85,0x7b,0x46,0x27,0xda,0xd0,0x6a,0x69,0x64,0x74,0xa9,0xb9,0xd7,0x82,0xb5,
+0x96,0xf2,0xd5,0x0c,0xb1,0xcc,0x23,0x5b,0x2b,0xd3,0x98,0x95,0x47,0xdb,0x98,0xc3,
+0x32,0x75,0xbf,0x75,0x92,0x13,0xcb,0xb4,0xfa,0x40,0x2b,0xb4,0xd3,0x34,0xda,0x0f,
+0x91,0x46,0xe3,0xaf,0x65,0xd6,0x1c,0xcb,0x07,0xfa,0x5c,0x82,0x1d,0x4a,0x25,0xa1,
+0x71,0xd2,0x94,0xdf,0xc8,0x4d,0x4f,0x92,0xfa,0x21,0x28,0x84,0x46,0xe8,0x93,0xad,
+0x55,0x3f,0x34,0x8f,0x26,0x87,0xf4,0xb1,0xdb,0x11,0x87,0x1f,0x64,0x4c,0xbd,0x87,
+0x60,0xee,0x21,0xea,0x03,0xf3,0x16,0x3b,0x90,0x4c,0x00,0x2e,0x7e,0xb8,0x1f,0x38,
+0xc4,0x99,0x76,0x2c,0x63,0x70,0x41,0xde,0xd6,0x3a,0x71,0xc8,0xd7,0x12,0xde,0x0c,
+0x3f,0x44,0xba,0x31,0x88,0xc6,0x67,0xcd,0x64,0x66,0x16,0x5f,0xcb,0xbc,0xbd,0x88,
+0x56,0xc4,0x64,0xc5,0x60,0x92,0xd2,0x88,0xbc,0x11,0xb1,0xc8,0xdf,0x9b,0xf8,0x6e,
+0xcc,0xce,0xa1,0xbd,0x24,0x8b,0x73,0x72,0x6b,0xf8,0x61,0xd7,0x6a,0xb2,0x18,0xdb,
+0x64,0xf3,0x3d,0x18,0x83,0x66,0x4f,0x8c,0x15,0xf7,0x72,0x4b,0x0e,0xbd,0xf8,0xa4,
+0x67,0xac,0xac,0x74,0xad,0x7a,0x7b,0x65,0xfb,0x4c,0x0f,0x33,0x89,0xaa,0x91,0xdb,
+0xbb,0xbd,0xe3,0xd2,0xb2,0x02,0xe6,0x35,0x5b,0x7a,0x2b,0x58,0x69,0x6e,0x5c,0xda,
+0x0c,0x3f,0x44,0xba,0x3f,0x74,0x72,0xd1,0x5e,0x66,0xf4,0xc2,0x88,0xdc,0xd6,0xfd,
+0x91,0x38,0x23,0x6f,0x6f,0xe2,0x6d,0x8d,0xc3,0xa4,0x0b,0x85,0xd1,0x16,0x8a,0x4b,
+0xbb,0x56,0x2b,0xff,0x6a,0xc2,0x99,0x56,0xb1,0x4d,0xc8,0xa1,0xad,0xf7,0xd0,0x87,
+0x6b,0x39,0x65,0xc6,0xb1,0x7a,0x21,0x6e,0xed,0xaf,0x47,0xbe,0xe7,0xc6,0x08,0x73,
+0x08,0xdc,0x0f,0xae,0x00,0x22,0xd7,0x9b,0x43,0x5e,0x3f,0x6c,0x16,0x87,0x68,0x6d,
+0xb8,0xce,0x05,0x6b,0x39,0xa2,0x17,0xc6,0x24,0xa1,0x11,0x9f,0x7b,0x3b,0xb9,0x7e,
+0xae,0xde,0xc4,0x77,0x39,0x38,0xc4,0xf5,0xc3,0x7a,0xbf,0x47,0x3e,0xa1,0xfa,0x21,
+0x19,0x07,0x8b,0xe7,0x89,0xe0,0xd1,0xe8,0x66,0x67,0x44,0xb7,0x57,0xe6,0x10,0x9d,
+0x49,0x5e,0x62,0x77,0x2c,0xe7,0x11,0x75,0x66,0x0a,0x71,0x69,0x5f,0x0e,0x2f,0x4c,
+0x97,0x95,0x75,0xa3,0x5d,0x94,0xac,0xdf,0x41,0xdd,0x1e,0xac,0x15,0x58,0x56,0x2e,
+0x04,0xbe,0xf2,0x51,0x7d,0xda,0x69,0x46,0xe3,0x78,0x6e,0xc1,0xb9,0xea,0xfb,0x41,
+0x97,0xff,0x1b,0xfb,0xd1,0xf8,0x5b,0xd3,0x84,0xb8,0xd7,0xd0,0x66,0x8d,0x4c,0xa9,
+0x17,0x92,0xc8,0x34,0x2d,0xed,0xe4,0x6e,0x73,0xcc,0xb5,0xe5,0xf1,0x43,0x54,0x0a,
+0xf2,0xf9,0xb1,0xfb,0x43,0xe1,0x91,0xfa,0x14,0x7e,0x6f,0x42,0x7e,0x18,0xa5,0xe3,
+0x61,0x9d,0xf3,0x77,0xe8,0x7e,0x68,0xe1,0x10,0xb6,0x96,0x96,0x7d,0xad,0x56,0x64,
+0xf5,0x43,0x4b,0x54,0x2a,0xb3,0x79,0x32,0xad,0xc3,0xe1,0xcd,0xc1,0xf0,0xc8,0xe7,
+0xc7,0x58,0x41,0xd7,0xcc,0x1b,0x2a,0x64,0x7f,0x77,0xe8,0xc8,0x02,0x65,0x8e,0xf6,
+0x1b,0x3a,0x15,0x34,0xbb,0x33,0x3e,0x76,0x9e,0xbb,0xbc,0x38,0xe6,0x7e,0x2e,0x06,
+0xef,0x87,0xa3,0xf1,0x48,0xbe,0x64,0xfb,0xc6,0xec,0x97,0xfd,0x14,0x77,0x62,0x98,
+0x87,0x0d,0x70,0x64,0x75,0xe3,0xe5,0x10,0x3d,0x5f,0xfd,0x4a,0x59,0xe1,0x39,0x56,
+0xa4,0x88,0x56,0x3f,0x34,0x46,0x1c,0x98,0xe6,0x84,0xa0,0x3e,0xe0,0x2f,0x41,0x6b,
+0x0d,0xe2,0xd0,0x79,0x34,0x4d,0xc9,0xe7,0xec,0x69,0xe7,0x8c,0x8d,0xd0,0x0f,0xd5,
+0x96,0xe2,0xb0,0x37,0xbc,0x94,0x71,0xa6,0x88,0xd1,0x04,0x37,0xe3,0xdd,0xe0,0x19,
+0x4e,0xb0,0x8d,0xb4,0xc2,0x63,0x79,0x8b,0x3e,0x42,0xb9,0x98,0x95,0xdd,0x56,0x9f,
+0x0d,0xbe,0x7e,0xb8,0xa3,0xc7,0x4e,0x74,0x1e,0x9f,0xfd,0x9c,0x26,0x6b,0x75,0xd6,
+0xb5,0x24,0x8b,0x57,0x39,0x66,0x61,0xf0,0x73,0x18,0x70,0xd9,0x04,0xed,0xb2,0x9b,
+0xc9,0x62,0x49,0xfe,0x94,0x2b,0x53,0x46,0x97,0xce,0x21,0xcc,0x07,0x80,0x3f,0x63,
+0x63,0xbe,0x24,0x6d,0xaf,0xc1,0x1c,0xc2,0x5e,0x0b,0x32,0xf7,0x30,0x2d,0xf9,0x6b,
+0xcf,0x74,0xca,0xc8,0x01,0xce,0x4c,0x3a,0x3a,0xba,0x3e,0xeb,0x01,0x79,0x17,0x8a,
+0x31,0xcd,0x33,0x98,0xe8,0x25,0x32,0x7f,0x82,0xd6,0xfb,0x4c,0xde,0x57,0xc5,0x07,
+0xf9,0xa9,0xb6,0x92,0x1a,0x2b,0xba,0xfd,0xfa,0xb9,0xf9,0x21,0xad,0xf9,0x73,0x72,
+0xd8,0x1b,0x4a,0x4b,0xe8,0x4c,0x33,0x46,0x4e,0x2b,0xe6,0xf5,0x70,0x0d,0x2e,0x2d,
+0x7d,0x74,0xa4,0xf7,0x3c,0x48,0x0a,0xf9,0x6a,0x74,0x4d,0xe3,0xd0,0x56,0x6e,0x72,
+0xcd,0xd1,0xff,0xbf,0x39,0x70,0xb4,0xda,0x27,0x86,0x3f,0x5f,0x90,0xa1,0x83,0x64,
+0xe2,0x28,0x76,0xad,0xae,0x65,0x9c,0x32,0x26,0xfa,0x9d,0x23,0x56,0xad,0x7e,0x68,
+0x5e,0xd7,0x9b,0x67,0xd4,0x78,0xfd,0x85,0x62,0x4c,0x38,0x6f,0xb0,0x00,0xfe,0x92,
+0x31,0xa4,0x34,0xdf,0x0a,0x58,0x0f,0xde,0xb2,0x26,0x6f,0x60,0x44,0xba,0x8d,0x5c,
+0x0a,0xba,0x7e,0xd8,0x1b,0x46,0x1c,0xda,0xf3,0xb7,0xc4,0xa8,0x0f,0x1a,0x63,0xa8,
+0xe1,0x6a,0xd5,0x9b,0xf0,0xdc,0x82,0x7b,0x6b,0x8f,0x3a,0x3f,0x87,0x7c,0x91,0x5e,
+0xb3,0x39,0x64,0xef,0x9e,0x2f,0x57,0x06,0xee,0xb7,0x88,0x92,0xc7,0x19,0x19,0x3b,
+0xca,0x60,0xfe,0x24,0x76,0xc4,0x58,0x31,0x92,0xdf,0x26,0x1c,0xd2,0x5e,0x0b,0x55,
+0xf6,0xbf,0x5e,0xd8,0xde,0x4f,0xcc,0x7e,0x58,0x62,0x7e,0x28,0xc3,0x5c,0xe0,0xad,
+0xc4,0x21,0x98,0xbd,0x0b,0x7c,0x91,0xe4,0x99,0xa1,0x23,0xd6,0x4c,0x3e,0x68,0x5a,
+0xd1,0x2a,0x10,0x2f,0xe4,0xe5,0xd0,0xbd,0x7e,0xe8,0xc5,0x0f,0x8f,0x19,0x1c,0x46,
+0x8d,0x55,0xe2,0xf1,0x38,0x15,0x3c,0x8b,0x2f,0x0a,0xb9,0xb2,0xf4,0x94,0xfb,0x25,
+0xce,0x99,0x42,0xde,0x95,0xaf,0x9b,0xcd,0x21,0x2b,0x7c,0x7e,0xd8,0x95,0x47,0x47,
+0x1b,0xc5,0xbf,0x63,0xa6,0xdf,0x2a,0x7c,0x0b,0x9b,0xb9,0x8c,0xda,0x8c,0x71,0xab,
+0x15,0xcb,0x4c,0x53,0x4b,0x8b,0xb7,0x7d,0xc6,0x15,0x23,0x91,0xd5,0x0d,0xb3,0x2d,
+0xc5,0x21,0x9c,0x5b,0x4f,0x58,0x2c,0xc9,0x30,0xff,0x18,0x6b,0x03,0x55,0x4d,0x11,
+0x69,0xed,0x34,0x5a,0x09,0x72,0xcb,0x0d,0xe6,0xee,0x87,0xa4,0xc6,0xc1,0x19,0x97,
+0xea,0x1c,0x12,0xb2,0xa2,0xa0,0x36,0x68,0x8c,0xdb,0xa4,0xfc,0x59,0xc9,0x0b,0x8e,
+0xc4,0x64,0x91,0x37,0xf3,0x7e,0xeb,0x70,0xc8,0xe7,0x87,0x11,0xdd,0x0f,0xd9,0x27,
+0x86,0x0b,0xa2,0x8f,0xee,0xf5,0xba,0x63,0x6c,0x13,0x73,0x08,0x33,0x44,0x4d,0xd6,
+0xb4,0x02,0xcc,0x5e,0xce,0x7e,0x9e,0x90,0x33,0x50,0x05,0x2b,0xd4,0xb4,0x12,0x87,
+0x30,0x2a,0x55,0x69,0x9e,0x99,0x02,0xec,0x9f,0x37,0x66,0xd8,0x7b,0x8f,0x3e,0x79,
+0xe8,0x83,0xd1,0xa4,0x57,0x3f,0xb4,0x8f,0x94,0xc2,0x97,0x92,0x9e,0xfc,0x90,0x9c,
+0x25,0x76,0xc2,0xa2,0x01,0x7b,0x9f,0x13,0x85,0xfc,0xbd,0x7d,0x98,0xc3,0xa4,0xfe,
+0xa8,0xca,0x5b,0xac,0xca,0x3e,0xa8,0xc2,0xe7,0x87,0x91,0x3c,0x79,0x5d,0x36,0x1f,
+0x24,0x6a,0x27,0x53,0xbb,0x9e,0xd0,0x38,0x64,0x63,0x69,0x50,0x66,0x1a,0x9e,0x76,
+0xab,0xca,0x72,0xf2,0x43,0x7c,0x26,0xaf,0xcb,0x90,0xc2,0xb4,0xc3,0x1a,0x35,0xcd,
+0x10,0xab,0x1f,0x5a,0x32,0x00,0xd2,0x91,0xdc,0x25,0xd6,0x52,0x83,0x59,0xb4,0x66,
+0xc9,0x0d,0x90,0x46,0x1e,0x3f,0x74,0x8a,0x4b,0xed,0x39,0xad,0xbd,0xfa,0x61,0xd4,
+0xdc,0x3e,0x53,0xa4,0x75,0x1a,0x47,0x3a,0x83,0xe5,0x90,0x7f,0x1d,0x1a,0xe2,0x87,
+0x56,0xaa,0x82,0xa6,0xcc,0xbd,0xf0,0xf9,0xa1,0xd1,0x16,0x8d,0x7b,0xf0,0x49,0x9c,
+0x01,0x3e,0x5f,0xec,0x85,0x98,0x43,0xd8,0x4a,0x53,0x90,0x6b,0x1d,0x01,0xa2,0x71,
+0xb8,0x69,0xa7,0x50,0x35,0xad,0x5f,0x8a,0x56,0x4e,0x6c,0x25,0x0e,0x59,0xbd,0x90,
+0x44,0xa2,0x05,0x1a,0x8d,0xd2,0x88,0x5a,0x61,0xe3,0x46,0xbd,0x12,0xe8,0xee,0x83,
+0xb4,0xdc,0xf1,0xe2,0x87,0xf6,0x75,0x8e,0x58,0x56,0x5d,0x2f,0x7e,0x98,0x2c,0x56,
+0xf0,0xc0,0x3a,0xf5,0x56,0x24,0xc1,0xde,0xdb,0xd8,0x17,0x3e,0x3f,0xf4,0xb2,0xc1,
+0xe3,0x09,0x9e,0xc3,0xb5,0x4c,0xd2,0xf8,0x1c,0x69,0xeb,0x33,0x6c,0xd9,0x02,0xfd,
+0x44,0xa9,0x3c,0x5a,0x6f,0x2d,0xa5,0x73,0x98,0x95,0x6b,0x1f,0x1b,0x5c,0xc9,0x0f,
+0x61,0x0b,0x0d,0xce,0x66,0xc2,0x3f,0x97,0xaa,0x9e,0x82,0xf5,0x43,0xd5,0xa8,0x17,
+0x92,0x96,0x98,0x75,0x05,0xf6,0x12,0x92,0xb5,0x72,0xaa,0xf5,0x17,0xfa,0x8f,0x48,
+0x09,0x59,0xfe,0xda,0x69,0xac,0x63,0x35,0x3c,0xd7,0x0f,0x8b,0xf5,0x25,0xaf,0x32,
+0x91,0xc9,0xa2,0x97,0xd9,0x3c,0xd0,0x0f,0x9b,0x49,0xa1,0x17,0x0e,0x4d,0x71,0x84,
+0x29,0xca,0xa7,0xbd,0x42,0xda,0x3e,0x25,0xb1,0xbc,0xa5,0x89,0xfc,0x67,0x3d,0xfc,
+0x9f,0x89,0xb3,0xac,0x1c,0x92,0xa8,0x14,0xb6,0xd0,0xcc,0xe9,0x1c,0xb6,0x46,0xff,
+0x21,0xe6,0x90,0xd0,0x47,0x33,0x00,0xd3,0x76,0x18,0x15,0x8e,0x1f,0xf5,0x4d,0x1f,
+0x97,0x17,0x22,0x8a,0x5c,0x73,0xb8,0xdb,0x39,0x84,0x2b,0x1f,0xe9,0x7f,0xf5,0x56,
+0x71,0xcf,0x7e,0x58,0xa7,0x7a,0x60,0x75,0x12,0xf8,0x5b,0x4a,0xb1,0x88,0x1f,0xfa,
+0x2d,0x31,0xb0,0xf7,0x4f,0x29,0xba,0x8d,0xaf,0x7e,0xf8,0x41,0xce,0xe9,0xf1,0x3a,
+0x83,0x80,0xc5,0xa8,0xce,0x21,0x6b,0x2b,0x7d,0x71,0xcc,0xcb,0x67,0xe2,0x2c,0x33,
+0x87,0x2c,0x2a,0x55,0x4d,0x75,0x43,0x54,0xf8,0xde,0x49,0xbd,0xc5,0xe2,0x52,0x53,
+0xc6,0x27,0xdc,0x5a,0xa3,0x10,0x2e,0x55,0x9f,0xfd,0x84,0x5e,0x49,0x74,0xf7,0xc3,
+0x67,0x47,0x2a,0x65,0x1e,0x82,0xeb,0xa6,0xf8,0xf1,0xc3,0x46,0x8c,0x9b,0x81,0x67,
+0x37,0xde,0xbc,0x8d,0x60,0x66,0x1c,0xc6,0x1c,0xc8,0x0a,0x26,0x62,0xe5,0x2b,0x7c,
+0x7e,0xb8,0x9d,0x01,0xcf,0xb8,0x69,0xa7,0xcf,0xe8,0x23,0xd2,0xf6,0x28,0xbb,0x0f,
+0x72,0xc3,0xac,0x1c,0xcc,0x98,0x64,0x27,0x0e,0x4b,0xa6,0xfe,0x8a,0x65,0x23,0x7f,
+0x57,0xeb,0xf8,0x21,0x6b,0x1f,0x45,0xe4,0xad,0xd3,0xf6,0x18,0x3f,0xe3,0x65,0xfc,
+0x7b,0x21,0x2a,0x31,0x57,0x3f,0xbc,0x3a,0x01,0x33,0x0f,0x59,0x57,0x37,0xa2,0xb9,
+0xad,0x3d,0xd4,0x0f,0xe7,0x24,0xfe,0xb3,0xcf,0x2b,0x65,0x95,0x7d,0x10,0xef,0xbd,
+0xb9,0x61,0xed,0x7e,0x18,0x9c,0x47,0xf2,0xb9,0xc8,0x76,0x45,0x3f,0x24,0x64,0x92,
+0x82,0xa2,0x51,0x7f,0x39,0x7b,0x9c,0xe5,0xec,0x87,0xa0,0x8d,0x46,0xf7,0x42,0x54,
+0x1b,0x6d,0x15,0x0e,0xcb,0x4a,0x01,0xf8,0xa0,0x8d,0x40,0x3a,0x86,0xc6,0x3a,0xab,
+0x29,0x68,0x2f,0xc4,0x71,0xa9,0x9b,0x1f,0x22,0x0e,0xa1,0x0f,0xc2,0xb5,0x8f,0xe8,
+0xa5,0xa2,0xe7,0x7e,0x8b,0x00,0x7d,0x90,0x8f,0x46,0x5c,0xbc,0xce,0xe7,0x09,0x96,
+0xc3,0x98,0xc3,0xbe,0x3a,0x7d,0xac,0x78,0x6a,0xa7,0x71,0x2c,0xe6,0x96,0x1b,0xc4,
+0x61,0x5a,0x8b,0x4d,0xf9,0xc6,0xad,0xba,0xcb,0x89,0xc3,0x75,0x45,0x35,0xd5,0x0d,
+0x27,0x5b,0x8a,0x43,0xd2,0x22,0x53,0xa2,0x99,0x66,0x68,0x3d,0xb0,0xa6,0x7a,0xa1,
+0x9f,0xc2,0xe7,0x87,0x96,0xf9,0xdc,0x77,0x30,0x8f,0x64,0x76,0x0d,0xee,0xa1,0x6a,
+0x94,0x1f,0x56,0x27,0x2d,0xe6,0x78,0xfe,0xe3,0x32,0xe5,0xd9,0x0d,0x11,0x87,0x6a,
+0xe0,0x7e,0xc8,0x4b,0xac,0x79,0xe3,0xe3,0xf0,0xc0,0x59,0xde,0xcf,0x36,0xab,0xc7,
+0x88,0xf1,0x00,0x6a,0x86,0x58,0xe6,0x19,0xc8,0xe4,0x7c,0xb6,0x46,0xa5,0xad,0xc4,
+0x61,0x59,0xff,0x9d,0x20,0x19,0x10,0x0b,0x8c,0x29,0xb9,0x64,0xce,0xfe,0xe4,0x3b,
+0x32,0xe5,0x2f,0xee,0xed,0x34,0xe7,0xc7,0x92,0xa0,0x7e,0x08,0xfc,0x10,0xdd,0x0a,
+0x56,0x5f,0x49,0x16,0xb7,0x39,0x39,0xcc,0x06,0x30,0x42,0x05,0x7a,0x06,0x2f,0x91,
+0x53,0x9e,0xdd,0xb0,0x91,0x1c,0x56,0x7a,0x2f,0xe4,0x7d,0xf0,0xae,0xc5,0x76,0x64,
+0x31,0x06,0x9e,0xb3,0x0a,0x87,0x9a,0x3f,0xd5,0xb2,0x02,0x8f,0x55,0x3b,0x36,0x3f,
+0xd4,0xa2,0x52,0xc5,0xdc,0x63,0x81,0x39,0x6c,0x8d,0xfe,0x43,0xb4,0xd6,0x3b,0x9d,
+0x53,0xa1,0xd4,0x36,0x9f,0xa2,0x36,0x2f,0xe4,0xf3,0xc3,0x73,0x71,0x74,0x2f,0xb2,
+0x72,0x26,0x5c,0xe3,0x01,0xcc,0x8d,0xd0,0xb6,0xa9,0x22,0xef,0xec,0xd1,0xbd,0xdc,
+0xa9,0x8a,0x14,0xd5,0xab,0x4c,0x15,0xa7,0xb6,0xfc,0xd5,0x84,0x12,0xf9,0x53,0x5b,
+0xf6,0x67,0x63,0xfb,0x29,0xcb,0x75,0xa7,0xfb,0xd5,0x5a,0x4e,0x15,0x0b,0xf2,0x65,
+0xee,0xb5,0x8d,0xdf,0x18,0x3c,0x70,0xf6,0xc8,0xc2,0x5e,0x2e,0x2d,0xa1,0x5e,0xdd,
+0x4a,0x4c,0x16,0xe4,0x93,0x01,0xd5,0x0c,0xb1,0x0e,0x9c,0x45,0xcf,0x8a,0xe3,0x5e,
+0x13,0x8d,0x26,0x12,0xd3,0x52,0x73,0xb2,0x18,0xd9,0xf5,0xdc,0x74,0x99,0x9b,0xae,
+0x5a,0x08,0xb3,0xe6,0xaf,0x24,0x6d,0x9b,0x74,0xf5,0x4c,0x7d,0xcc,0x45,0x92,0x23,
+0x5f,0xf3,0xfb,0xb3,0x25,0x90,0x51,0x01,0xae,0xb6,0xc9,0xc6,0x6b,0x94,0x95,0xbd,
+0xdc,0xcb,0x9c,0x67,0xca,0xb9,0xf8,0x77,0xa4,0x5a,0xdf,0x97,0x75,0x83,0x9f,0x9b,
+0xd3,0x67,0x39,0x27,0xf9,0x1d,0x2f,0xf2,0xc6,0x60,0x2a,0x5f,0x02,0xdf,0x84,0x79,
+0x54,0x22,0x2c,0xaa,0x65,0x5f,0x70,0xb9,0x1f,0x5f,0x41,0x31,0x5d,0x2a,0x1f,0xf6,
+0xb5,0x4e,0xce,0x68,0x3c,0x3e,0x76,0x6d,0x76,0x66,0x31,0x91,0xcf,0xca,0x28,0x62,
+0x81,0xde,0x3b,0x29,0xbd,0x13,0x50,0xcd,0x90,0xe8,0xc2,0x34,0xcc,0xdf,0x8c,0xf3,
+0xc7,0xa2,0x7c,0xb2,0x7b,0x39,0x9c,0xdb,0x12,0xe5,0x45,0x78,0x78,0xa9,0x75,0x56,
+0x03,0x46,0x19,0xe1,0xc9,0x1a,0x0c,0x64,0x1d,0x06,0xeb,0x7a,0x0c,0x4e,0x6b,0x34,
+0x38,0x95,0x49,0xd7,0x92,0xb6,0x5c,0x32,0x3f,0xf7,0xe0,0x62,0x0f,0xc7,0x11,0xf7,
+0xf7,0xde,0x1d,0x22,0xe5,0xa6,0xe3,0xde,0x6b,0xac,0x81,0xf2,0x59,0xf8,0x58,0xa9,
+0xb3,0xc2,0x36,0x1a,0xef,0xef,0xad,0x5e,0xfc,0x7c,0x4f,0x4c,0x4f,0xb2,0x67,0xd2,
+0x5e,0xe9,0xd3,0xd8,0xed,0x06,0x96,0xef,0x87,0x83,0xc8,0x40,0x75,0xb9,0xf3,0x8d,
+0xc1,0x5b,0x13,0x0f,0x2f,0xed,0x68,0x2e,0x89,0xb2,0xb1,0x15,0x6a,0x1c,0x4d,0x1a,
+0xac,0x5e,0x09,0x15,0x43,0x77,0xf4,0xed,0x4a,0x68,0x21,0xf4,0x5b,0x0d,0x7b,0xdd,
+0x63,0xe1,0x77,0x3a,0x2f,0x77,0xda,0xb7,0x77,0x1c,0xf6,0x4e,0xe5,0x5d,0xf4,0x37,
+0xf6,0xae,0x76,0x9f,0xde,0x70,0x6f,0xb8,0x27,0xdc,0xeb,0x58,0x2a,0xdd,0x4e,0x4a,
+0x6b,0x64,0x18,0x13,0x6a,0xb4,0x9e,0xec,0x7d,0x75,0xf0,0xfb,0x2d,0xf5,0xdd,0xab,
+0x47,0x57,0x8e,0x5f,0xd4,0xca,0x94,0x56,0x7e,0x3c,0xbe,0x92,0xba,0x98,0x92,0x5f,
+0xf8,0xe1,0xa1,0x67,0x3b,0xf8,0x1e,0xdd,0x11,0x3a,0xcf,0x79,0x4f,0x21,0x21,0xa1,
+0xca,0x7a,0xee,0xe0,0xca,0x71,0x5c,0xe6,0xb5,0x6d,0x77,0xbc,0xfb,0xcc,0xf0,0xb9,
+0xc7,0xe3,0xf3,0x09,0xb9,0xef,0xa3,0xa7,0xdc,0x1f,0x7d,0xb0,0x6f,0x7e,0xb8,0x58,
+0xff,0x83,0x14,0x12,0xda,0xf7,0x3a,0xd8,0xf7,0xa1,0xc6,0xe0,0xbc,0xe6,0x89,0x68,
+0x5b,0x19,0x7f,0xf4,0xbd,0xee,0x73,0x8f,0x53,0xd7,0x87,0x4f,0xf5,0xff,0xdd,0x33,
+0xd5,0x1f,0xf9,0x2b,0xbf,0x3c,0x3f,0x3c,0x3f,0xfc,0x7b,0x07,0x1b,0x73,0x9c,0x42,
+0x42,0xfb,0x59,0x1d,0xa1,0x2f,0xf4,0xd8,0x74,0x5e,0x8f,0x4f,0x2f,0x22,0x57,0x4c,
+0x75,0x9f,0xc1,0x24,0xbe,0xf6,0x42,0x4f,0xc5,0x28,0xfa,0x46,0xe8,0xf9,0x04,0xe2,
+0x50,0x3e,0xdc,0xc8,0xa3,0x15,0x12,0xda,0xaf,0xfa,0x7a,0xc7,0x14,0xa5,0x50,0xab,
+0x27,0x0e,0x5f,0x3c,0xfe,0xa1,0x16,0x9f,0x76,0x9f,0xd9,0x38,0x3e,0x3f,0xb0,0xf6,
+0xdd,0xff,0x51,0xa1,0x6d,0x77,0xf9,0xf0,0xfc,0xf0,0xd4,0x30,0xda,0x44,0x64,0x2a,
+0x24,0x14,0x84,0x50,0x2d,0xf1,0x22,0x20,0x71,0x0a,0xc7,0xa7,0x1a,0x89,0x17,0xc7,
+0xff,0xf5,0x52,0xbf,0x43,0x36,0xc7,0x9f,0x1d,0x42,0x04,0x6a,0xcc,0x0e,0xaf,0x0c,
+0xff,0x50,0x44,0xa6,0x42,0x42,0x81,0xe8,0x60,0xdf,0x8a,0x46,0xa0,0x41,0xa1,0x5e,
+0xe6,0xf5,0xf8,0x74,0x77,0xfc,0xef,0x17,0x7e,0x7f,0xd1,0x3a,0xa2,0xe8,0x6a,0x07,
+0xb9,0xd7,0x94,0x88,0x4c,0x85,0x84,0x02,0x53,0x47,0x48,0x3d,0x3a,0xaf,0xf7,0x5e,
+0x58,0x49,0x8c,0x5d,0xe9,0xca,0xcf,0x2c,0x9e,0x07,0xa3,0x61,0x8f,0x6b,0x35,0x4a,
+0x72,0x9f,0x8b,0x28,0x32,0x4d,0xdc,0x68,0xde,0x81,0x0b,0x09,0xed,0x2b,0x7d,0xbd,
+0xe3,0xf9,0x61,0x48,0xa1,0x4e,0xd9,0xf1,0x8d,0xf1,0x53,0x6f,0x65,0xe5,0x48,0x7e,
+0x29,0xc3,0x72,0x29,0x1c,0xed,0x83,0xf7,0xd1,0x4a,0xe2,0x7f,0x8b,0x5e,0x44,0x21,
+0xa1,0x80,0xf4,0xdc,0xc1,0x8b,0x30,0x32,0xd5,0xf7,0xf3,0x89,0x53,0x57,0xa6,0xb6,
+0x54,0x39,0x91,0x5f,0xcb,0x5c,0x98,0xee,0xd1,0xee,0xf5,0x9f,0x0e,0x9a,0x48,0xd5,
+0x28,0x4c,0x0e,0xfc,0x9b,0xa8,0x21,0x0a,0x09,0x05,0xa6,0x3f,0x3d,0xf4,0xfa,0xe1,
+0xcc,0x61,0xf9,0xa8,0x7c,0xf4,0xef,0x8f,0xaa,0x47,0xbf,0xd0,0x8a,0xda,0x57,0xfe,
+0xd1,0x75,0xf5,0xd4,0x56,0x49,0x99,0x94,0x76,0x72,0xef,0xcf,0xfe,0x79,0x6f,0xf9,
+0x68,0xd2,0xe4,0x86,0xc9,0x44,0xb9,0xef,0xf5,0xee,0x66,0x1f,0xb9,0x90,0xd0,0x7e,
+0x12,0x99,0x5b,0xd2,0x11,0xfa,0x5a,0xa8,0x4f,0x2b,0x1d,0xa1,0x5f,0x9c,0xde,0x50,
+0xaf,0xab,0xf3,0x5b,0x65,0x05,0xad,0x98,0x77,0x72,0xe1,0x3f,0x8f,0x27,0x13,0x90,
+0xc3,0xe8,0x40,0xb9,0x7b,0xb9,0xef,0x95,0xe6,0x1e,0xb6,0x90,0xd0,0xbe,0xd1,0xe5,
+0xce,0x5f,0x9c,0x3e,0xb2,0x70,0x6d,0xd6,0xdc,0x77,0x7f,0x7f,0x08,0x71,0x78,0x5d,
+0x5d,0xd9,0x42,0x33,0x27,0xb7,0x73,0xff,0xeb,0xb7,0x92,0x89,0xe4,0x30,0xf5,0xc4,
+0x44,0xb4,0x5f,0xed,0x96,0xfb,0xae,0x34,0xeb,0xa0,0x85,0x84,0xf6,0x95,0xce,0x8f,
+0x7d,0xf3,0x47,0x33,0x8b,0x3b,0xb9,0x49,0xc9,0x9c,0xdd,0x21,0x3c,0x82,0x39,0xd4,
+0x48,0xd4,0xe2,0xd3,0x6f,0x2e,0xfc,0x6d,0xc7,0x14,0xa3,0x70,0xf8,0xf9,0x81,0x2f,
+0xfa,0xe4,0xae,0x97,0xfa,0x1a,0x37,0x53,0x43,0x48,0x68,0xbf,0xea,0xe6,0xd0,0xfb,
+0xb3,0x27,0x17,0xd7,0x32,0x91,0x3c,0x9a,0xc1,0x3c,0xbf,0x05,0xf3,0x3b,0x10,0x3f,
+0xbc,0xae,0x6e,0xa8,0xc9,0xe2,0xed,0x58,0x7f,0x28,0x9a,0x98,0x4a,0x50,0x37,0x1c,
+0x50,0xbb,0x97,0xbb,0x7e,0xee,0x32,0x12,0x55,0x48,0x48,0xa8,0xba,0xbe,0x1d,0xbf,
+0x30,0x7d,0x72,0x71,0x29,0xb3,0xa7,0x39,0x21,0xca,0x44,0x32,0xbf,0x85,0x88,0x63,
+0xeb,0x1f,0xdc,0x1d,0xc2,0x5e,0x88,0xfe,0xe2,0x99,0x93,0xaf,0xf7,0xc1,0x36,0x1a,
+0xb5,0x2b,0xd3,0xfd,0x17,0x2d,0x33,0xc3,0x58,0x48,0xa8,0xfd,0xf4,0xdf,0x3b,0x1f,
+0x68,0x35,0xc2,0x99,0xcc,0x4e,0x0e,0xe5,0x0d,0x40,0x4e,0x48,0x9c,0x6f,0x7e,0x8b,
+0xe4,0x94,0xc2,0x1c,0xa2,0xdb,0x48,0x36,0x8f,0x5f,0x41,0x3d,0x17,0x09,0x1c,0x95,
+0xaa,0xdf,0x58,0x7e,0x62,0xfb,0xbb,0x62,0x3e,0xad,0x90,0x90,0x4f,0x85,0xaf,0x8e,
+0x3d,0xf5,0xfa,0x6b,0x0b,0x1f,0x2c,0x46,0x56,0xd3,0x1a,0x83,0x53,0x5b,0x2b,0xba,
+0x13,0x12,0xea,0x4a,0x0a,0xa6,0xeb,0x8d,0x41,0xec,0x90,0x59,0x99,0x3c,0xf0,0x0a,
+0x8a,0x4c,0x51,0xbf,0x61,0x7f,0xe9,0x89,0x6f,0x0d,0xcb,0x0b,0xc1,0x64,0x43,0x16,
+0x12,0xfa,0xea,0x69,0xe0,0x99,0x5f,0x1d,0xbf,0x38,0xfe,0xe1,0xf8,0xa3,0xd4,0xa3,
+0x57,0xfe,0xfd,0x95,0xa1,0x2b,0xff,0x20,0x0d,0x15,0x37,0xd4,0x5d,0x83,0x43,0xf4,
+0x77,0x57,0xc5,0xeb,0xc6,0x23,0x0e,0x37,0xd4,0x53,0x5b,0xe7,0xc0,0x68,0xef,0xae,
+0xae,0xa9,0x81,0x8b,0xe3,0x5f,0xbe,0x7e,0x71,0x79,0x5d,0x4e,0x49,0xb5,0xe6,0x3e,
+0x11,0x12,0xfa,0x2a,0x2a,0x1f,0x92,0x8f,0xce,0x0f,0x5c,0x1f,0xf8,0xe4,0xf8,0xe3,
+0xd4,0xe3,0xd4,0x6e,0x6a,0x77,0x7c,0x63,0x7c,0xe5,0xf8,0x5f,0xf7,0x7e,0x7e,0x6c,
+0x29,0x53,0x52,0xae,0xeb,0x34,0x6e,0xe8,0x34,0xa2,0x15,0xd4,0x3f,0xeb,0x29,0x2b,
+0xb0,0xbe,0x88,0xf4,0xf6,0x77,0x3f,0x5c,0x3d,0xb5,0x89,0xfb,0xf7,0xdd,0xb3,0x9d,
+0x09,0x09,0x09,0x59,0x75,0x25,0x54,0x3e,0x7c,0x7d,0x60,0x03,0x31,0xf8,0xbd,0x47,
+0x88,0xc2,0xd4,0x86,0xb6,0x7d,0xf1,0x02,0xf9,0xff,0xcd,0xa1,0x8f,0x2f,0x65,0xe5,
+0x53,0x9a,0x07,0x7e,0x72,0x0f,0xc7,0xa2,0x9f,0xc6,0xd8,0x7c,0x8b,0xf8,0xd8,0x52,
+0xa6,0xac,0xe0,0xd8,0x75,0x7e,0x2b,0xb6,0x99,0x96,0xee,0xb7,0xc4,0xda,0x35,0x42,
+0x42,0xed,0x25,0xf9,0xf0,0x5f,0x0e,0x7f,0x32,0xde,0x7d,0x86,0x50,0x88,0xcb,0xb5,
+0x43,0xe6,0x7b,0x8d,0xc6,0x4f,0x4c,0x27,0x4c,0x39,0x23,0xc3,0x23,0x88,0xc0,0x0d,
+0xc3,0x2b,0x51,0x39,0xb5,0x55,0x56,0x5a,0x25,0x27,0xaa,0x90,0x50,0x3b,0xe9,0x4f,
+0x0f,0x3d,0xd6,0xe7,0xda,0x3f,0x32,0x51,0xb8,0x32,0xee,0x92,0xd2,0x5a,0xab,0x25,
+0x5e,0x07,0x04,0xe2,0xf1,0x35,0xc9,0x62,0x41,0x7e,0xcf,0x73,0x9e,0x76,0x21,0xa1,
+0xaf,0xba,0x9e,0x09,0x7d,0x98,0x7a,0x01,0x51,0x98,0x82,0x14,0xee,0xa6,0xe4,0x17,
+0x9c,0xee,0x0d,0xdb,0x5f,0x46,0xe3,0xc9,0xe2,0xae,0x89,0x44,0x34,0xe2,0x34,0x92,
+0x6f,0xad,0x2c,0x90,0x42,0x42,0xed,0x20,0xe9,0x99,0x61,0x07,0x0a,0x77,0x53,0xdf,
+0xb0,0xcc,0x5b,0xba,0x31,0xf8,0xfe,0x6c,0x41,0x9e,0xdf,0x82,0x99,0xd8,0x3f,0xeb,
+0x79,0x70,0x3a,0x91,0x4f,0x16,0x49,0x64,0x3a,0xa5,0xb9,0xe1,0x5b,0xa2,0xc7,0x42,
+0x48,0xc8,0xb3,0x9e,0x47,0xf5,0x42,0x9d,0x42,0x48,0xe2,0xc5,0xf1,0xaf,0xd1,0x7b,
+0x7c,0x7e,0xec,0xc8,0x42,0x49,0xc6,0x6d,0xa6,0x9f,0xdc,0x4b,0xeb,0xab,0x74,0x5d,
+0x9d,0x60,0x3c,0xde,0x8e,0xdd,0x9a,0x40,0xeb,0xbc,0x5d,0x57,0xd1,0xfa,0x00,0x4e,
+0x99,0x6b,0x84,0x84,0x84,0xaa,0xe9,0xd7,0x3a,0x1e,0x7f,0x4f,0x2b,0x29,0x44,0xe2,
+0x23,0x83,0xc6,0xc7,0xa9,0x8d,0xd4,0x4f,0xf5,0xd1,0xa1,0x2f,0x8e,0x2d,0x65,0x92,
+0x46,0x1f,0xe2,0x86,0x31,0xa6,0x06,0xad,0xd9,0x30,0x1a,0xbf,0xae,0x11,0x69,0xee,
+0x9d,0xb8,0xdc,0x19,0x1e,0xe9,0xfc,0xd1,0x6f,0xbc,0x2e,0xa6,0xe1,0x0b,0x09,0x79,
+0x55,0xe7,0x61,0xd4,0x4a,0x8a,0x4b,0xf7,0xe4,0xe3,0xd4,0x8f,0xc7,0xe5,0x17,0x4e,
+0x1c,0xba,0x83,0xff,0xb7,0x80,0xda,0x42,0x1f,0xdf,0xfb,0xe4,0x1e,0xe9,0xc9,0xdf,
+0x50,0xf1,0x38,0x99,0x57,0xf5,0x7e,0xfc,0x0d,0xf5,0xbc,0x69,0xbd,0xc6,0xd1,0x50,
+0xaa,0x6f,0x2a,0xf1,0xc5,0xd1,0x7f,0x7b,0xe6,0x7c,0xc7,0xd7,0x1c,0x5e,0x4b,0x48,
+0x48,0xc8,0x59,0x7f,0xa0,0xb7,0x94,0x22,0x16,0xa7,0xc6,0x5f,0x3a,0xfa,0x2f,0x4f,
+0xc1,0xb9,0x4a,0xb8,0xcf,0xf0,0x13,0xca,0xe1,0x27,0x2a,0x59,0x15,0xf0,0x5c,0x1c,
+0x73,0x38,0x55,0x1c,0xa5,0x51,0xe8,0xef,0x1d,0x4c,0x0e,0xe3,0x4c,0xfc,0xa8,0x44,
+0x87,0x0f,0xf6,0xbd,0x29,0x68,0x14,0x12,0xe2,0xd0,0xaf,0x75,0x74,0x9f,0xd9,0x4d,
+0x7d,0xeb,0xf8,0xc3,0x5f,0xff,0x9d,0x5f,0xb2,0xff,0xf7,0xd6,0x44,0x5a,0x42,0x2d,
+0xa2,0x8f,0xef,0xe1,0x76,0x98,0x58,0x91,0xac,0x1a,0x8e,0xfd,0x10,0x39,0x64,0x41,
+0xef,0xd5,0xbf,0x12,0x7a,0xfd,0xf0,0x8a,0x9e,0x89,0x9f,0x94,0x95,0xe3,0x1b,0xc7,
+0x3f,0x14,0x34,0x0a,0x09,0x71,0xa8,0x23,0xf4,0x2f,0x4f,0xdd,0xa9,0xf8,0xdf,0x73,
+0xf1,0x54,0x1e,0x47,0xa6,0xb8,0x7e,0xc8,0xa2,0x50,0xec,0x87,0xd7,0xf5,0x11,0xa7,
+0x4b,0x99,0xf7,0x3a,0x9e,0x1f,0xc6,0x59,0xf8,0x19,0x85,0xb8,0x5c,0xd7,0x68,0xdc,
+0x38,0x9e,0x1c,0x7e,0xa9,0x4f,0x0c,0x74,0x13,0x12,0xf2,0xa7,0x63,0xe1,0xb5,0x4c,
+0x49,0x9e,0xdf,0x42,0x35,0xc4,0x5d,0x53,0xab,0x0c,0xf1,0x43,0x5c,0x6b,0x3c,0x75,
+0x65,0x3e,0x81,0xe9,0x63,0x04,0xae,0x00,0x16,0x77,0xb5,0xdb,0xbf,0x2e,0x9a,0x6f,
+0x84,0x84,0x7c,0xaa,0x73,0x01,0xd7,0x10,0x1f,0xdf,0xfb,0xcd,0xcd,0xbf,0xf9,0x0f,
+0xec,0x76,0xe4,0x87,0xd8,0x23,0xf5,0x76,0xd4,0xad,0x7f,0xff,0xa3,0x53,0x89,0x79,
+0x47,0x0a,0x91,0x1f,0xca,0x87,0xdd,0x46,0xe6,0x08,0x09,0x09,0x55,0xd6,0xc0,0xd9,
+0xb4,0x14,0x2b,0xee,0xde,0xfb,0x44,0xfd,0xcd,0xf4,0xca,0xf1,0x0b,0x74,0xbc,0xe9,
+0x68,0x7c,0x43,0x7d,0xfa,0xfe,0xe3,0x7b,0xa8,0x20,0x4a,0xff,0x5b,0xf1,0xc7,0xe3,
+0xc9,0x81,0x29,0x94,0x1b,0x43,0x5f,0xef,0x09,0x97,0x95,0xe1,0xeb,0x1a,0x9b,0x3f,
+0x3b,0x54,0xed,0x15,0x84,0x84,0x84,0xdc,0x74,0x7f,0x68,0x52,0x42,0x35,0xc4,0xdd,
+0xd5,0x8d,0xe3,0xa8,0x77,0x7f,0xf6,0x28,0x6e,0x73,0x39,0x17,0xdf,0xbd,0xf7,0xf4,
+0xfd,0xee,0x7f,0xd4,0x37,0xed,0xef,0xf0,0xfd,0x43,0x05,0xb5,0x4b,0xed,0xfa,0xa2,
+0xaf,0xdc,0x17,0xed,0xc7,0x25,0x39,0x90,0x1c,0x90,0xfb,0x78,0x57,0x11,0x16,0x12,
+0x12,0xaa,0xa4,0x77,0x63,0x7b,0xb9,0x92,0xf2,0x0f,0xf9,0x8d,0xf1,0xdd,0x71,0x3c,
+0xce,0xe6,0x79,0xbd,0xa6,0x77,0x73,0xe8,0xd4,0xd6,0xbc,0x31,0x57,0x7f,0x43,0x1f,
+0x65,0xf3,0xf8,0xde,0xd4,0xf2,0xeb,0x4f,0x2c,0x3f,0xb1,0xdc,0xbd,0xdc,0x2d,0x6b,
+0x45,0xd5,0xca,0x0f,0x7f,0xb9,0xd9,0xc7,0x2f,0x24,0xb4,0x3f,0x74,0x72,0x31,0x2b,
+0xfd,0x38,0xb5,0x32,0x0c,0xe7,0x61,0xfc,0xae,0x46,0xe2,0x81,0xb3,0xd7,0x66,0x8f,
+0x2c,0xa0,0x4c,0x52,0x89,0x7c,0x5a,0x2a,0xc8,0xb1,0xcd,0xa9,0xe2,0xb7,0x96,0xff,
+0xec,0x85,0xa3,0xdf,0x78,0xa9,0xeb,0xa5,0xae,0xd9,0xee,0x9f,0x1f,0xba,0xdf,0xec,
+0x43,0x17,0x12,0xda,0x37,0x7a,0x6b,0xf6,0x8b,0xc5,0xe8,0x81,0x95,0xe3,0x8c,0xc3,
+0xc7,0xa9,0x8f,0x2d,0x19,0x11,0x8f,0x85,0x3f,0xeb,0x79,0x63,0x30,0x3c,0xf2,0xe0,
+0xf4,0xdf,0x4e,0x8c,0xff,0xc6,0x89,0x43,0x07,0x0e,0xfd,0x73,0x73,0x0e,0x56,0x48,
+0x68,0x9f,0xea,0xfc,0xc4,0xe4,0x2b,0xe5,0x27,0xe6,0x87,0x77,0xc7,0xc9,0x28,0xf0,
+0x47,0xc6,0xd8,0x53,0x21,0x21,0xa1,0x46,0x69,0x34,0xfe,0xff,0xfe,0x4b,0xf9,0x89,
+0xa9,0x04,0xa9,0x1f,0x3e,0x72,0xf0,0x43,0x21,0x21,0xa1,0xfa,0xea,0x58,0x78,0xe2,
+0xa8,0xfa,0x8d,0xe4,0xc0,0xc6,0x38,0x99,0x8f,0xf1,0x58,0xf8,0xa1,0x90,0x50,0xc3,
+0xf5,0xf3,0x5f,0x57,0xbb,0x62,0xfd,0x2b,0x7a,0x1e,0xb7,0xc7,0xc2,0x0f,0x85,0x84,
+0x9a,0xa2,0x37,0x9f,0x52,0xfb,0xa2,0x4f,0xcf,0x0f,0x3f,0x4a,0x61,0x12,0xbb,0x27,
+0xaf,0x09,0x0e,0x85,0x84,0x1a,0xae,0x9f,0x3d,0x13,0x7b,0x7a,0x3e,0xb1,0x4b,0x38,
+0x3c,0xf3,0x96,0x18,0x21,0x23,0x24,0xd4,0x04,0x1d,0xec,0x3e,0x35,0xb0,0x3b,0x4e,
+0xfc,0x50,0x70,0x28,0x24,0xd4,0x1c,0xfd,0xdd,0xa1,0xdd,0xf1,0xee,0x49,0x94,0x41,
+0xa3,0xfb,0xcc,0x1f,0x09,0x0e,0x85,0x84,0x9a,0xa4,0x0b,0x87,0x76,0x53,0x28,0xa3,
+0x54,0xf7,0x99,0xc3,0x82,0x43,0x21,0xa1,0xa6,0xe9,0x0f,0x7f,0xe9,0xe2,0xf8,0xf0,
+0x99,0xa7,0x05,0x87,0x42,0x42,0x4d,0x55,0x47,0x68,0xf6,0xe8,0xb0,0xe0,0x50,0x48,
+0xa8,0xed,0xf5,0xff,0x01,0xd1,0x0a,0xff,0xc9,0xa6,0xee,0x01,0x00};
+#endif
diff --git a/lib/tpm-common.c b/lib/tpm-common.c
new file mode 100644
index 00000000..86b4f413
--- /dev/null
+++ b/lib/tpm-common.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#define LOG_CATEGORY UCLASS_TPM
+
+#include <common.h>
+#include <dm.h>
+#include <asm/unaligned.h>
+#include <tpm-common.h>
+#include "tpm-utils.h"
+
+enum tpm_version tpm_get_version(struct udevice *dev)
+{
+ struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+
+ return priv->version;
+}
+
+int pack_byte_string(u8 *str, size_t size, const char *format, ...)
+{
+ va_list args;
+ size_t offset = 0, length = 0;
+ u8 *data = NULL;
+ u32 value = 0;
+
+ va_start(args, format);
+ for (; *format; format++) {
+ switch (*format) {
+ case 'b':
+ offset = va_arg(args, size_t);
+ value = va_arg(args, int);
+ length = 1;
+ break;
+ case 'w':
+ offset = va_arg(args, size_t);
+ value = va_arg(args, int);
+ length = 2;
+ break;
+ case 'd':
+ offset = va_arg(args, size_t);
+ value = va_arg(args, u32);
+ length = 4;
+ break;
+ case 's':
+ offset = va_arg(args, size_t);
+ data = va_arg(args, u8 *);
+ length = va_arg(args, u32);
+ break;
+ default:
+ debug("Couldn't recognize format string\n");
+ va_end(args);
+ return -1;
+ }
+
+ if (offset + length > size) {
+ va_end(args);
+ return -1;
+ }
+
+ switch (*format) {
+ case 'b':
+ str[offset] = value;
+ break;
+ case 'w':
+ put_unaligned_be16(value, str + offset);
+ break;
+ case 'd':
+ put_unaligned_be32(value, str + offset);
+ break;
+ case 's':
+ memcpy(str + offset, data, length);
+ break;
+ }
+ }
+ va_end(args);
+
+ return 0;
+}
+
+int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
+{
+ va_list args;
+ size_t offset = 0, length = 0;
+ u8 *ptr8 = NULL;
+ u16 *ptr16 = NULL;
+ u32 *ptr32 = NULL;
+
+ va_start(args, format);
+ for (; *format; format++) {
+ switch (*format) {
+ case 'b':
+ offset = va_arg(args, size_t);
+ ptr8 = va_arg(args, u8 *);
+ length = 1;
+ break;
+ case 'w':
+ offset = va_arg(args, size_t);
+ ptr16 = va_arg(args, u16 *);
+ length = 2;
+ break;
+ case 'd':
+ offset = va_arg(args, size_t);
+ ptr32 = va_arg(args, u32 *);
+ length = 4;
+ break;
+ case 's':
+ offset = va_arg(args, size_t);
+ ptr8 = va_arg(args, u8 *);
+ length = va_arg(args, u32);
+ break;
+ default:
+ va_end(args);
+ debug("Couldn't recognize format string\n");
+ return -1;
+ }
+
+ if (offset + length > size) {
+ va_end(args);
+ log_err("Failed to read: size=%zd, offset=%zx, len=%zx\n",
+ size, offset, length);
+ return -1;
+ }
+
+ switch (*format) {
+ case 'b':
+ *ptr8 = str[offset];
+ break;
+ case 'w':
+ *ptr16 = get_unaligned_be16(str + offset);
+ break;
+ case 'd':
+ *ptr32 = get_unaligned_be32(str + offset);
+ break;
+ case 's':
+ memcpy(ptr8, str + offset, length);
+ break;
+ }
+ }
+ va_end(args);
+
+ return 0;
+}
+
+u32 tpm_command_size(const void *command)
+{
+ const size_t command_size_offset = 2;
+
+ return get_unaligned_be32(command + command_size_offset);
+}
+
+u32 tpm_return_code(const void *response)
+{
+ const size_t return_code_offset = 6;
+
+ return get_unaligned_be32(response + return_code_offset);
+}
+
+u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
+ void *response, size_t *size_ptr)
+{
+ int err, ret;
+ u8 response_buffer[COMMAND_BUFFER_SIZE];
+ size_t response_length;
+ int i;
+
+ if (response) {
+ response_length = *size_ptr;
+ } else {
+ response = response_buffer;
+ response_length = sizeof(response_buffer);
+ }
+
+ err = tpm_xfer(dev, command, tpm_command_size(command),
+ response, &response_length);
+
+ if (err < 0)
+ return err;
+
+ if (size_ptr)
+ *size_ptr = response_length;
+
+ ret = tpm_return_code(response);
+
+ log_debug("TPM response [ret:%d]: ", ret);
+ for (i = 0; i < response_length; i++)
+ log_debug("%02x ", ((u8 *)response)[i]);
+ log_debug("\n");
+
+ return ret;
+}
+
+int tpm_init(struct udevice *dev)
+{
+ return tpm_open(dev);
+}
diff --git a/lib/tpm-utils.h b/lib/tpm-utils.h
new file mode 100644
index 00000000..d680d140
--- /dev/null
+++ b/lib/tpm-utils.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_UTILS_H
+#define __TPM_UTILS_H
+
+#define COMMAND_BUFFER_SIZE 256
+
+/* Internal error of TPM command library */
+#define TPM_LIB_ERROR ((u32)~0u)
+
+/* To make strings of commands more easily */
+#define __MSB(x) ((x) >> 8)
+#define __LSB(x) ((x) & 0xFF)
+#define tpm_u16(x) __MSB(x), __LSB(x)
+#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
+
+/**
+ * Pack data into a byte string. The data types are specified in
+ * the format string: 'b' means unsigned byte, 'w' unsigned word,
+ * 'd' unsigned double word, and 's' byte string. The data are a
+ * series of offsets and values (for type byte string there are also
+ * lengths). The data values are packed into the byte string
+ * sequentially, and so a latter value could over-write a former
+ * value.
+ *
+ * @param str output string
+ * @param size size of output string
+ * @param format format string
+ * @param ... data points
+ * @return 0 on success, non-0 on error
+ */
+int pack_byte_string(u8 *str, size_t size, const char *format, ...);
+
+/**
+ * Unpack data from a byte string. The data types are specified in
+ * the format string: 'b' means unsigned byte, 'w' unsigned word,
+ * 'd' unsigned double word, and 's' byte string. The data are a
+ * series of offsets and pointers (for type byte string there are also
+ * lengths).
+ *
+ * @param str output string
+ * @param size size of output string
+ * @param format format string
+ * @param ... data points
+ * @return 0 on success, non-0 on error
+ */
+int unpack_byte_string(const u8 *str, size_t size, const char *format, ...);
+
+/**
+ * Get TPM command size.
+ *
+ * @param command byte string of TPM command
+ * @return command size of the TPM command
+ */
+u32 tpm_command_size(const void *command);
+
+/**
+ * Get TPM response return code, which is one of TPM_RESULT values.
+ *
+ * @param response byte string of TPM response
+ * @return return code of the TPM response
+ */
+u32 tpm_return_code(const void *response);
+
+/**
+ * Send a TPM command and return response's return code, and optionally
+ * return response to caller.
+ *
+ * @param command byte string of TPM command
+ * @param response output buffer for TPM response, or NULL if the
+ * caller does not care about it
+ * @param size_ptr output buffer size (input parameter) and TPM
+ * response length (output parameter); this parameter
+ * is a bidirectional
+ * @return return code of the TPM response
+ */
+u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
+ void *response, size_t *size_ptr);
+
+#endif /* __TPM_UTILS_H */
diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
new file mode 100644
index 00000000..b4498e6a
--- /dev/null
+++ b/lib/tpm-v1.c
@@ -0,0 +1,920 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#define LOG_CATEGORY UCLASS_TPM
+
+#include <common.h>
+#include <dm.h>
+#include <asm/unaligned.h>
+#include <u-boot/sha1.h>
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include "tpm-utils.h"
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+#ifndef CONFIG_SHA1
+#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
+#endif /* !CONFIG_SHA1 */
+
+struct session_data {
+ int valid;
+ u32 handle;
+ u8 nonce_even[DIGEST_LENGTH];
+ u8 nonce_odd[DIGEST_LENGTH];
+};
+
+static struct session_data oiap_session = {0, };
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
+{
+ const u8 command[12] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
+ };
+ const size_t mode_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE];
+
+ if (pack_byte_string(buf, sizeof(buf), "sw",
+ 0, command, sizeof(command),
+ mode_offset, mode))
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, buf, NULL, NULL);
+}
+
+u32 tpm_resume(struct udevice *dev)
+{
+ return tpm_startup(dev, TPM_ST_STATE);
+}
+
+u32 tpm_self_test_full(struct udevice *dev)
+{
+ const u8 command[10] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
+ };
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_continue_self_test(struct udevice *dev)
+{
+ const u8 command[10] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
+ };
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_clear_and_reenable(struct udevice *dev)
+{
+ u32 ret;
+
+ log_info("TPM: Clear and re-enable\n");
+ ret = tpm_force_clear(dev);
+ if (ret != TPM_SUCCESS) {
+ log_err("Can't initiate a force clear\n");
+ return ret;
+ }
+
+ if (tpm_get_version(dev) == TPM_V1) {
+ ret = tpm_physical_enable(dev);
+ if (ret != TPM_SUCCESS) {
+ log_err("TPM: Can't set enabled state\n");
+ return ret;
+ }
+
+ ret = tpm_physical_set_deactivated(dev, 0);
+ if (ret != TPM_SUCCESS) {
+ log_err("TPM: Can't set deactivated state\n");
+ return ret;
+ }
+ }
+
+ return TPM_SUCCESS;
+}
+
+u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
+{
+ const u8 command[101] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0x65, /* parameter size */
+ 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
+ /* TPM_NV_DATA_PUBLIC->... */
+ 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
+ 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
+ /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
+ 0x0, 0x3,
+ 0, 0, 0,
+ 0x1f,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
+ 0x0, 0x3,
+ 0, 0, 0,
+ 0x1f,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* TPM_NV_ATTRIBUTES->... */
+ 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
+ 0, 0, 0, 0, /* ...->attributes */
+ /* End of TPM_NV_ATTRIBUTES */
+ 0, /* bReadSTClear */
+ 0, /* bWriteSTClear */
+ 0, /* bWriteDefine */
+ 0, 0, 0, 0, /* size */
+ };
+ const size_t index_offset = 12;
+ const size_t perm_offset = 70;
+ const size_t size_offset = 77;
+ u8 buf[COMMAND_BUFFER_SIZE];
+
+ if (pack_byte_string(buf, sizeof(buf), "sddd",
+ 0, command, sizeof(command),
+ index_offset, index,
+ perm_offset, perm,
+ size_offset, size))
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, buf, NULL, NULL);
+}
+
+u32 tpm_nv_set_locked(struct udevice *dev)
+{
+ return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
+}
+
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
+{
+ const u8 command[22] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
+ };
+ const size_t index_offset = 10;
+ const size_t length_offset = 18;
+ const size_t data_size_offset = 10;
+ const size_t data_offset = 14;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 data_size;
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sdd",
+ 0, command, sizeof(command),
+ index_offset, index,
+ length_offset, count))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ data_size_offset, &data_size))
+ return TPM_LIB_ERROR;
+ if (data_size > count)
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, data, data_size))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+ u32 length)
+{
+ const u8 command[256] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
+ };
+ const size_t command_size_offset = 2;
+ const size_t index_offset = 10;
+ const size_t length_offset = 18;
+ const size_t data_offset = 22;
+ const size_t write_info_size = 12;
+ const u32 total_length =
+ TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sddds",
+ 0, command, sizeof(command),
+ command_size_offset, total_length,
+ index_offset, index,
+ length_offset, length,
+ data_offset, data, length))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+uint32_t tpm_set_global_lock(struct udevice *dev)
+{
+ return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
+}
+
+u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
+ void *out_digest)
+{
+ const u8 command[34] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
+ };
+ const size_t index_offset = 10;
+ const size_t in_digest_offset = 14;
+ const size_t out_digest_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE];
+ u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sds",
+ 0, command, sizeof(command),
+ index_offset, index,
+ in_digest_offset, in_digest,
+ PCR_DIGEST_LENGTH))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+
+ if (unpack_byte_string(response, response_length, "s",
+ out_digest_offset, out_digest,
+ PCR_DIGEST_LENGTH))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
+{
+ const u8 command[14] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
+ };
+ const size_t index_offset = 10;
+ const size_t out_digest_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (count < PCR_DIGEST_LENGTH)
+ return TPM_LIB_ERROR;
+
+ if (pack_byte_string(buf, sizeof(buf), "sd",
+ 0, command, sizeof(command),
+ index_offset, index))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "s",
+ out_digest_offset, data, PCR_DIGEST_LENGTH))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
+{
+ const u8 command[12] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
+ };
+ const size_t presence_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE];
+
+ if (pack_byte_string(buf, sizeof(buf), "sw",
+ 0, command, sizeof(command),
+ presence_offset, presence))
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, buf, NULL, NULL);
+}
+
+u32 tpm_finalise_physical_presence(struct udevice *dev)
+{
+ const u8 command[12] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
+ };
+
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
+{
+ const u8 command[30] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
+ };
+ const size_t response_size_offset = 2;
+ const size_t data_offset = 10;
+ const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
+ u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
+ size_t response_length = sizeof(response);
+ u32 data_size;
+ u32 err;
+
+ err = tpm_sendrecv_command(dev, command, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ response_size_offset, &data_size))
+ return TPM_LIB_ERROR;
+ if (data_size < header_and_checksum_size)
+ return TPM_LIB_ERROR;
+ data_size -= header_and_checksum_size;
+ if (data_size > count)
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, data, data_size))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+u32 tpm_force_clear(struct udevice *dev)
+{
+ const u8 command[10] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
+ };
+
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_physical_enable(struct udevice *dev)
+{
+ const u8 command[10] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
+ };
+
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_physical_disable(struct udevice *dev)
+{
+ const u8 command[10] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
+ };
+
+ return tpm_sendrecv_command(dev, command, NULL, NULL);
+}
+
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
+{
+ const u8 command[11] = {
+ 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
+ };
+ const size_t state_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE];
+
+ if (pack_byte_string(buf, sizeof(buf), "sb",
+ 0, command, sizeof(command),
+ state_offset, state))
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, buf, NULL, NULL);
+}
+
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+ void *cap, size_t count)
+{
+ const u8 command[22] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0x16, /* parameter size */
+ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
+ 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
+ 0x0, 0x0, 0x0, 0x4, /* subcap size */
+ 0x0, 0x0, 0x0, 0x0, /* subcap value */
+ };
+ const size_t cap_area_offset = 10;
+ const size_t sub_cap_offset = 18;
+ const size_t cap_offset = 14;
+ const size_t cap_size_offset = 10;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 cap_size;
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sdd",
+ 0, command, sizeof(command),
+ cap_area_offset, cap_area,
+ sub_cap_offset, sub_cap))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ cap_size_offset, &cap_size))
+ return TPM_LIB_ERROR;
+ if (cap_size > response_length || cap_size > count)
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ cap_offset, cap, cap_size))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+u32 tpm_get_permanent_flags(struct udevice *dev,
+ struct tpm_permanent_flags *pflags)
+{
+ const u8 command[22] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0x16, /* parameter size */
+ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
+ 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
+ 0x0, 0x0, 0x0, 0x4, /* subcap size */
+ 0x0, 0x0, 0x1, 0x8, /* subcap value */
+ };
+ const size_t data_size_offset = TPM_HEADER_SIZE;
+ const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
+ u8 response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+ u32 data_size;
+
+ err = tpm_sendrecv_command(dev, command, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ data_size_offset, &data_size)) {
+ log_err("Cannot unpack data size\n");
+ return TPM_LIB_ERROR;
+ }
+ if (data_size < sizeof(*pflags)) {
+ log_err("Data size too small\n");
+ return TPM_LIB_ERROR;
+ }
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, pflags, sizeof(*pflags))) {
+ log_err("Cannot unpack pflags\n");
+ return TPM_LIB_ERROR;
+ }
+
+ return 0;
+}
+
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
+{
+ const u8 command[22] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0x16, /* parameter size */
+ 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
+ 0x0, 0x0, 0x0, 0x11,
+ 0x0, 0x0, 0x0, 0x4,
+ };
+ const size_t index_offset = 18;
+ const size_t perm_offset = 60;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
+ index_offset, index))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ perm_offset, perm))
+ return TPM_LIB_ERROR;
+
+ return 0;
+}
+
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
+{
+ const u8 command[18] = {
+ 0x00, 0xc1, /* TPM_TAG */
+ 0x00, 0x00, 0x00, 0x12, /* parameter size */
+ 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+ 0x00, 0x00, 0x00, 0x00, /* key handle */
+ 0x00, 0x00, 0x00, 0x00, /* resource type */
+ };
+ const size_t key_handle_offset = 10;
+ const size_t resource_type_offset = 14;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sdd",
+ 0, command, sizeof(command),
+ key_handle_offset, key_handle,
+ resource_type_offset, resource_type))
+ return TPM_LIB_ERROR;
+
+ err = tpm_sendrecv_command(dev, buf, response, &response_length);
+ if (err)
+ return err;
+ return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+/**
+ * Fill an authentication block in a request.
+ * This func can create the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param request pointer to the request (w/ uninitialised auth data)
+ * @param request_len0 length of the request without auth data
+ * @param handles_len length of the handles area in request
+ * @param auth_session pointer to the (valid) auth session to be used
+ * @param request_auth pointer to the auth block of the request to be filled
+ * @param auth authentication data (HMAC key)
+ */
+static u32 create_request_auth(const void *request, size_t request_len0,
+ size_t handles_len,
+ struct session_data *auth_session,
+ void *request_auth, const void *auth)
+{
+ u8 hmac_data[DIGEST_LENGTH * 3 + 1];
+ sha1_context hash_ctx;
+ const size_t command_code_offset = 6;
+ const size_t auth_nonce_odd_offset = 4;
+ const size_t auth_continue_offset = 24;
+ const size_t auth_auth_offset = 25;
+
+ if (!auth_session || !auth_session->valid)
+ return TPM_LIB_ERROR;
+
+ sha1_starts(&hash_ctx);
+ sha1_update(&hash_ctx, request + command_code_offset, 4);
+ if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
+ sha1_update(&hash_ctx,
+ request + TPM_REQUEST_HEADER_LENGTH + handles_len,
+ request_len0 - TPM_REQUEST_HEADER_LENGTH
+ - handles_len);
+ sha1_finish(&hash_ctx, hmac_data);
+
+ sha1_starts(&hash_ctx);
+ sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
+ sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
+ sha1_finish(&hash_ctx, auth_session->nonce_odd);
+
+ if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
+ 0, auth_session->handle,
+ auth_nonce_odd_offset, auth_session->nonce_odd,
+ DIGEST_LENGTH,
+ auth_continue_offset, 1))
+ return TPM_LIB_ERROR;
+ if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
+ DIGEST_LENGTH,
+ auth_session->nonce_even,
+ DIGEST_LENGTH,
+ 2 * DIGEST_LENGTH,
+ request_auth + auth_nonce_odd_offset,
+ DIGEST_LENGTH + 1))
+ return TPM_LIB_ERROR;
+ sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+ request_auth + auth_auth_offset);
+
+ return TPM_SUCCESS;
+}
+
+/**
+ * Verify an authentication block in a response.
+ * Since this func updates the nonce_even in the session data it has to be
+ * called when receiving a succesfull AUTH response.
+ * This func can verify the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param command_code command code of the request
+ * @param response pointer to the request (w/ uninitialised auth data)
+ * @param handles_len length of the handles area in response
+ * @param auth_session pointer to the (valid) auth session to be used
+ * @param response_auth pointer to the auth block of the response to be verified
+ * @param auth authentication data (HMAC key)
+ */
+static u32 verify_response_auth(u32 command_code, const void *response,
+ size_t response_len0, size_t handles_len,
+ struct session_data *auth_session,
+ const void *response_auth, const void *auth)
+{
+ u8 hmac_data[DIGEST_LENGTH * 3 + 1];
+ u8 computed_auth[DIGEST_LENGTH];
+ sha1_context hash_ctx;
+ const size_t return_code_offset = 6;
+ const size_t auth_continue_offset = 20;
+ const size_t auth_auth_offset = 21;
+ u8 auth_continue;
+
+ if (!auth_session || !auth_session->valid)
+ return TPM_AUTHFAIL;
+ if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
+ 0, command_code))
+ return TPM_LIB_ERROR;
+ if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
+ return TPM_LIB_ERROR;
+
+ sha1_starts(&hash_ctx);
+ sha1_update(&hash_ctx, response + return_code_offset, 4);
+ sha1_update(&hash_ctx, hmac_data, 4);
+ if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
+ sha1_update(&hash_ctx,
+ response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
+ response_len0 - TPM_RESPONSE_HEADER_LENGTH
+ - handles_len);
+ sha1_finish(&hash_ctx, hmac_data);
+
+ memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
+ auth_continue = ((u8 *)response_auth)[auth_continue_offset];
+ if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
+ DIGEST_LENGTH,
+ response_auth,
+ DIGEST_LENGTH,
+ 2 * DIGEST_LENGTH,
+ auth_session->nonce_odd,
+ DIGEST_LENGTH,
+ 3 * DIGEST_LENGTH,
+ auth_continue))
+ return TPM_LIB_ERROR;
+
+ sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+ computed_auth);
+
+ if (memcmp(computed_auth, response_auth + auth_auth_offset,
+ DIGEST_LENGTH))
+ return TPM_AUTHFAIL;
+
+ return TPM_SUCCESS;
+}
+
+u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
+{
+ const u8 command[18] = {
+ 0x00, 0xc1, /* TPM_TAG */
+ 0x00, 0x00, 0x00, 0x00, /* parameter size */
+ 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+ 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
+ 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
+ };
+ const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+ u8 request[COMMAND_BUFFER_SIZE];
+
+ if (pack_byte_string(request, sizeof(request), "sd",
+ 0, command, sizeof(command),
+ req_handle_offset, auth_handle))
+ return TPM_LIB_ERROR;
+ if (oiap_session.valid && oiap_session.handle == auth_handle)
+ oiap_session.valid = 0;
+
+ return tpm_sendrecv_command(dev, request, NULL, NULL);
+}
+
+u32 tpm_end_oiap(struct udevice *dev)
+{
+ u32 err = TPM_SUCCESS;
+
+ if (oiap_session.valid)
+ err = tpm_terminate_auth_session(dev, oiap_session.handle);
+ return err;
+}
+
+u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
+{
+ const u8 command[10] = {
+ 0x00, 0xc1, /* TPM_TAG */
+ 0x00, 0x00, 0x00, 0x0a, /* parameter size */
+ 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
+ };
+ const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+ const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
+ u8 response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (oiap_session.valid)
+ tpm_terminate_auth_session(dev, oiap_session.handle);
+
+ err = tpm_sendrecv_command(dev, command, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "ds",
+ res_auth_handle_offset, &oiap_session.handle,
+ res_nonce_even_offset, &oiap_session.nonce_even,
+ (u32)DIGEST_LENGTH))
+ return TPM_LIB_ERROR;
+ oiap_session.valid = 1;
+ if (auth_handle)
+ *auth_handle = oiap_session.handle;
+ return 0;
+}
+
+u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+ size_t key_length, const void *parent_key_usage_auth,
+ u32 *key_handle)
+{
+ const u8 command[14] = {
+ 0x00, 0xc2, /* TPM_TAG */
+ 0x00, 0x00, 0x00, 0x00, /* parameter size */
+ 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
+ 0x00, 0x00, 0x00, 0x00, /* parent handle */
+ };
+ const size_t req_size_offset = 2;
+ const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+ const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
+ const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+ u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
+ TPM_REQUEST_AUTH_LENGTH];
+ u8 response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (!oiap_session.valid) {
+ err = tpm_oiap(dev, NULL);
+ if (err)
+ return err;
+ }
+ if (pack_byte_string(request, sizeof(request), "sdds",
+ 0, command, sizeof(command),
+ req_size_offset,
+ sizeof(command) + key_length
+ + TPM_REQUEST_AUTH_LENGTH,
+ req_parent_handle_offset, parent_handle,
+ req_key_offset, key, key_length
+ ))
+ return TPM_LIB_ERROR;
+
+ err = create_request_auth(request, sizeof(command) + key_length, 4,
+ &oiap_session,
+ request + sizeof(command) + key_length,
+ parent_key_usage_auth);
+ if (err)
+ return err;
+ err = tpm_sendrecv_command(dev, request, response, &response_length);
+ if (err) {
+ if (err == TPM_AUTHFAIL)
+ oiap_session.valid = 0;
+ return err;
+ }
+
+ err = verify_response_auth(0x00000041, response,
+ response_length - TPM_RESPONSE_AUTH_LENGTH,
+ 4, &oiap_session,
+ response + response_length -
+ TPM_RESPONSE_AUTH_LENGTH,
+ parent_key_usage_auth);
+ if (err)
+ return err;
+
+ if (key_handle) {
+ if (unpack_byte_string(response, response_length, "d",
+ res_handle_offset, key_handle))
+ return TPM_LIB_ERROR;
+ }
+
+ return 0;
+}
+
+u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+ const void *usage_auth, void *pubkey,
+ size_t *pubkey_len)
+{
+ const u8 command[14] = {
+ 0x00, 0xc2, /* TPM_TAG */
+ 0x00, 0x00, 0x00, 0x00, /* parameter size */
+ 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
+ 0x00, 0x00, 0x00, 0x00, /* key handle */
+ };
+ const size_t req_size_offset = 2;
+ const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+ const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
+ u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
+ u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
+ TPM_RESPONSE_AUTH_LENGTH];
+ size_t response_length = sizeof(response);
+ u32 err;
+
+ if (!oiap_session.valid) {
+ err = tpm_oiap(dev, NULL);
+ if (err)
+ return err;
+ }
+ if (pack_byte_string(request, sizeof(request), "sdd",
+ 0, command, sizeof(command),
+ req_size_offset,
+ (u32)(sizeof(command)
+ + TPM_REQUEST_AUTH_LENGTH),
+ req_key_handle_offset, key_handle
+ ))
+ return TPM_LIB_ERROR;
+ err = create_request_auth(request, sizeof(command), 4, &oiap_session,
+ request + sizeof(command), usage_auth);
+ if (err)
+ return err;
+ err = tpm_sendrecv_command(dev, request, response, &response_length);
+ if (err) {
+ if (err == TPM_AUTHFAIL)
+ oiap_session.valid = 0;
+ return err;
+ }
+ err = verify_response_auth(0x00000021, response,
+ response_length - TPM_RESPONSE_AUTH_LENGTH,
+ 0, &oiap_session,
+ response + response_length -
+ TPM_RESPONSE_AUTH_LENGTH,
+ usage_auth);
+ if (err)
+ return err;
+
+ if (pubkey) {
+ if ((response_length - TPM_RESPONSE_HEADER_LENGTH
+ - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
+ return TPM_LIB_ERROR;
+ *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
+ - TPM_RESPONSE_AUTH_LENGTH;
+ memcpy(pubkey, response + res_pubkey_offset,
+ response_length - TPM_RESPONSE_HEADER_LENGTH
+ - TPM_RESPONSE_AUTH_LENGTH);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
+ const u8 pubkey_digest[20], u32 *handle)
+{
+ u16 key_count;
+ u32 key_handles[10];
+ u8 buf[288];
+ u8 *ptr;
+ u32 err;
+ u8 digest[20];
+ size_t buf_len;
+ unsigned int i;
+
+ /* fetch list of already loaded keys in the TPM */
+ err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+ sizeof(buf));
+ if (err)
+ return -1;
+ key_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+ for (i = 0; i < key_count; ++i, ptr += 4)
+ key_handles[i] = get_unaligned_be32(ptr);
+
+ /* now search a(/ the) key which we can access with the given auth */
+ for (i = 0; i < key_count; ++i) {
+ buf_len = sizeof(buf);
+ err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+ if (err && err != TPM_AUTHFAIL)
+ return -1;
+ if (err)
+ continue;
+ sha1_csum(buf, buf_len, digest);
+ if (!memcmp(digest, pubkey_digest, 20)) {
+ *handle = key_handles[i];
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
+{
+ const u8 command[14] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0xe, /* parameter size */
+ 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
+ };
+ const size_t length_offset = 10;
+ const size_t data_size_offset = 10;
+ const size_t data_offset = 14;
+ u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ u32 data_size;
+ u8 *out = data;
+
+ while (count > 0) {
+ u32 this_bytes = min((size_t)count,
+ sizeof(response) - data_offset);
+ u32 err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sd",
+ 0, command, sizeof(command),
+ length_offset, this_bytes))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(dev, buf, response,
+ &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ data_size_offset, &data_size))
+ return TPM_LIB_ERROR;
+ if (data_size > count)
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, out, data_size))
+ return TPM_LIB_ERROR;
+
+ count -= data_size;
+ out += data_size;
+ }
+
+ return 0;
+}
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
new file mode 100644
index 00000000..f89592d6
--- /dev/null
+++ b/lib/tpm-v2.c
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Bootlin
+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <tpm-common.h>
+#include <tpm-v2.h>
+#include "tpm-utils.h"
+
+u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
+{
+ const u8 command_v2[12] = {
+ tpm_u16(TPM2_ST_NO_SESSIONS),
+ tpm_u32(12),
+ tpm_u32(TPM2_CC_STARTUP),
+ tpm_u16(mode),
+ };
+ int ret;
+
+ /*
+ * Note TPM2_Startup command will return RC_SUCCESS the first time,
+ * but will return RC_INITIALIZE otherwise.
+ */
+ ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+ if (ret && ret != TPM2_RC_INITIALIZE)
+ return ret;
+
+ return 0;
+}
+
+u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
+{
+ const u8 command_v2[12] = {
+ tpm_u16(TPM2_ST_NO_SESSIONS),
+ tpm_u32(11),
+ tpm_u32(TPM2_CC_SELF_TEST),
+ full_test,
+ };
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
+ const ssize_t pw_sz)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(27 + pw_sz), /* Length */
+ tpm_u32(TPM2_CC_CLEAR), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(handle), /* TPM resource handle */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz), /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+ };
+ unsigned int offset = 27;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the password (if any)
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
+ offset, pw, pw_sz);
+ offset += pw_sz;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_pcr_extend(struct udevice *dev, u32 index, const uint8_t *digest)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(33 + TPM2_DIGEST_LEN), /* Length */
+ tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(index), /* Handle (PCR Index) */
+
+ /* AUTH_SESSION */
+ tpm_u32(9), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(0), /* Size of <hmac/password> */
+ /* <hmac/password> (if any) */
+ tpm_u32(1), /* Count (number of hashes) */
+ tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */
+ /* STRING(digest) Digest */
+ };
+ unsigned int offset = 33;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the digest
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
+ offset, digest, TPM2_DIGEST_LEN);
+ offset += TPM2_DIGEST_LEN;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
+ void *data, unsigned int *updates)
+{
+ u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
+ tpm_u32(17 + idx_array_sz), /* Length */
+ tpm_u32(TPM2_CC_PCR_READ), /* Command code */
+
+ /* TPML_PCR_SELECTION */
+ tpm_u32(1), /* Number of selections */
+ tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */
+ idx_array_sz, /* Array size for selection */
+ /* bitmap(idx) Selected PCR bitmap */
+ };
+ size_t response_len = COMMAND_BUFFER_SIZE;
+ u8 response[COMMAND_BUFFER_SIZE];
+ unsigned int pcr_sel_idx = idx / 8;
+ u8 pcr_sel_bit = BIT(idx % 8);
+ unsigned int counter = 0;
+ int ret;
+
+ if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
+ 17 + pcr_sel_idx, pcr_sel_bit))
+ return TPM_LIB_ERROR;
+
+ ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
+ if (ret)
+ return ret;
+
+ if (unpack_byte_string(response, response_len, "ds",
+ 10, &counter,
+ response_len - TPM2_DIGEST_LEN, data,
+ TPM2_DIGEST_LEN))
+ return TPM_LIB_ERROR;
+
+ if (updates)
+ *updates = counter;
+
+ return 0;
+}
+
+u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
+ void *buf, size_t prop_count)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
+ tpm_u32(22), /* Length */
+ tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
+
+ tpm_u32(capability), /* Capability */
+ tpm_u32(property), /* Property */
+ tpm_u32(prop_count), /* Property count */
+ };
+ u8 response[COMMAND_BUFFER_SIZE];
+ size_t response_len = COMMAND_BUFFER_SIZE;
+ unsigned int properties_off;
+ int ret;
+
+ ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
+ if (ret)
+ return ret;
+
+ /*
+ * In the response buffer, the properties are located after the:
+ * tag (u16), response size (u32), response code (u32),
+ * YES/NO flag (u8), TPM_CAP (u32) and TPMU_CAPABILITIES (u32).
+ */
+ properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
+ sizeof(u8) + sizeof(u32) + sizeof(u32);
+ memcpy(buf, &response[properties_off], response_len - properties_off);
+
+ return 0;
+}
+
+u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(27 + pw_sz), /* Length */
+ tpm_u32(TPM2_CC_DAM_RESET), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz), /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+ };
+ unsigned int offset = 27;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the password (if any)
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
+ offset, pw, pw_sz);
+ offset += pw_sz;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
+ const ssize_t pw_sz, unsigned int max_tries,
+ unsigned int recovery_time,
+ unsigned int lockout_recovery)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(27 + pw_sz + 12), /* Length */
+ tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz), /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+
+ /* LOCKOUT PARAMETERS */
+ /* tpm_u32(max_tries) Max tries (0, always lock) */
+ /* tpm_u32(recovery_time) Recovery time (0, no lock) */
+ /* tpm_u32(lockout_recovery) Lockout recovery */
+ };
+ unsigned int offset = 27;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the password (if any)
+ * - max tries
+ * - recovery time
+ * - lockout recovery
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
+ offset, pw, pw_sz,
+ offset + pw_sz, max_tries,
+ offset + pw_sz + 4, recovery_time,
+ offset + pw_sz + 8, lockout_recovery);
+ offset += pw_sz + 12;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
+ const ssize_t newpw_sz, const char *oldpw,
+ const ssize_t oldpw_sz)
+{
+ unsigned int offset = 27;
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
+ tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(handle), /* TPM resource handle */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + oldpw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* Session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(oldpw_sz) /* Size of <hmac/password> */
+ /* STRING(oldpw) <hmac/password> (if any) */
+
+ /* TPM2B_AUTH (TPM2B_DIGEST) */
+ /* tpm_u16(newpw_sz) Digest size, new pw length */
+ /* STRING(newpw) Digest buffer, new pw */
+ };
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the old password (if any)
+ * - size of the new password
+ * - new password
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
+ offset, oldpw, oldpw_sz,
+ offset + oldpw_sz, newpw_sz,
+ offset + oldpw_sz + 2, newpw, newpw_sz);
+ offset += oldpw_sz + 2 + newpw_sz;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
+ const ssize_t pw_sz, u32 index, const char *key)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
+ tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz) /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+
+ /* TPM2B_AUTH (TPM2B_DIGEST) */
+ /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
+ /* STRING(key) Digest buffer (PCR key) */
+
+ /* TPMI_ALG_HASH */
+ /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
+
+ /* TPMI_DH_PCR */
+ /* tpm_u32(index), PCR Index */
+ };
+ unsigned int offset = 27;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the password (if any)
+ * - the PCR key length
+ * - the PCR key
+ * - the hash algorithm
+ * - the PCR index
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
+ offset, pw, pw_sz,
+ offset + pw_sz, TPM2_DIGEST_LEN,
+ offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
+ offset + pw_sz + 2 + TPM2_DIGEST_LEN,
+ TPM2_ALG_SHA256,
+ offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
+ offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
+
+u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
+ const ssize_t pw_sz, u32 index, const char *key,
+ const ssize_t key_sz)
+{
+ u8 command_v2[COMMAND_BUFFER_SIZE] = {
+ tpm_u16(TPM2_ST_SESSIONS), /* TAG */
+ tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
+ tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
+
+ /* HANDLE */
+ tpm_u32(index), /* Handle (PCR Index) */
+
+ /* AUTH_SESSION */
+ tpm_u32(9 + pw_sz), /* Authorization size */
+ tpm_u32(TPM2_RS_PW), /* session handle */
+ tpm_u16(0), /* Size of <nonce> */
+ /* <nonce> (if any) */
+ 0, /* Attributes: Cont/Excl/Rst */
+ tpm_u16(pw_sz), /* Size of <hmac/password> */
+ /* STRING(pw) <hmac/password> (if any) */
+
+ /* TPM2B_DIGEST */
+ /* tpm_u16(key_sz) Key length */
+ /* STRING(key) Key */
+ };
+ unsigned int offset = 27;
+ int ret;
+
+ /*
+ * Fill the command structure starting from the first buffer:
+ * - the password (if any)
+ * - the number of digests, 1 in our case
+ * - the algorithm, sha256 in our case
+ * - the digest (64 bytes)
+ */
+ ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
+ offset, pw, pw_sz,
+ offset + pw_sz, key_sz,
+ offset + pw_sz + 2, key, key_sz);
+ offset += pw_sz + 2 + key_sz;
+ if (ret)
+ return TPM_LIB_ERROR;
+
+ return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
+}
diff --git a/lib/trace.c b/lib/trace.c
new file mode 100644
index 00000000..6716c7c2
--- /dev/null
+++ b/lib/trace.c
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <time.h>
+#include <trace.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char trace_enabled __attribute__((section(".data")));
+static char trace_inited __attribute__((section(".data")));
+
+/* The header block at the start of the trace memory area */
+struct trace_hdr {
+ int func_count; /* Total number of function call sites */
+ u64 call_count; /* Total number of tracked function calls */
+ u64 untracked_count; /* Total number of untracked function calls */
+ int funcs_used; /* Total number of functions used */
+
+ /*
+ * Call count for each function. This is indexed by the word offset
+ * of the function from gd->relocaddr
+ */
+ uintptr_t *call_accum;
+
+ /* Function trace list */
+ struct trace_call *ftrace; /* The function call records */
+ ulong ftrace_size; /* Num. of ftrace records we have space for */
+ ulong ftrace_count; /* Num. of ftrace records written */
+ ulong ftrace_too_deep_count; /* Functions that were too deep */
+
+ int depth;
+ int depth_limit;
+ int max_depth;
+};
+
+static struct trace_hdr *hdr; /* Pointer to start of trace buffer */
+
+static inline uintptr_t __attribute__((no_instrument_function))
+ func_ptr_to_num(void *func_ptr)
+{
+ uintptr_t offset = (uintptr_t)func_ptr;
+
+#ifdef CONFIG_SANDBOX
+ offset -= (uintptr_t)&_init;
+#else
+ if (gd->flags & GD_FLG_RELOC)
+ offset -= gd->relocaddr;
+ else
+ offset -= CONFIG_SYS_TEXT_BASE;
+#endif
+ return offset / FUNC_SITE_SIZE;
+}
+
+#ifdef CONFIG_EFI_LOADER
+
+/**
+ * trace_gd - the value of the gd register
+ */
+static volatile void *trace_gd;
+
+/**
+ * trace_save_gd() - save the value of the gd register
+ */
+static void __attribute__((no_instrument_function)) trace_save_gd(void)
+{
+ trace_gd = gd;
+}
+
+/**
+ * trace_swap_gd() - swap between U-Boot and application gd register value
+ *
+ * An UEFI application may change the value of the register that gd lives in.
+ * But some of our functions like get_ticks() access this register. So we
+ * have to set the gd register to the U-Boot value when entering a trace
+ * point and set it back to the application value when exiting the trace point.
+ */
+static void __attribute__((no_instrument_function)) trace_swap_gd(void)
+{
+ volatile void *temp_gd = trace_gd;
+
+ trace_gd = gd;
+ gd = temp_gd;
+}
+
+#else
+
+static void __attribute__((no_instrument_function)) trace_save_gd(void)
+{
+}
+
+static void __attribute__((no_instrument_function)) trace_swap_gd(void)
+{
+}
+
+#endif
+
+static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
+ void *caller, ulong flags)
+{
+ if (hdr->depth > hdr->depth_limit) {
+ hdr->ftrace_too_deep_count++;
+ return;
+ }
+ if (hdr->ftrace_count < hdr->ftrace_size) {
+ struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+ rec->func = func_ptr_to_num(func_ptr);
+ rec->caller = func_ptr_to_num(caller);
+ rec->flags = flags | (timer_get_us() & FUNCF_TIMESTAMP_MASK);
+ }
+ hdr->ftrace_count++;
+}
+
+static void __attribute__((no_instrument_function)) add_textbase(void)
+{
+ if (hdr->ftrace_count < hdr->ftrace_size) {
+ struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+ rec->func = CONFIG_SYS_TEXT_BASE;
+ rec->caller = 0;
+ rec->flags = FUNCF_TEXTBASE;
+ }
+ hdr->ftrace_count++;
+}
+
+/**
+ * This is called on every function entry
+ *
+ * We add to our tally for this function and add to the list of called
+ * functions.
+ *
+ * @param func_ptr Pointer to function being entered
+ * @param caller Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
+ void *func_ptr, void *caller)
+{
+ if (trace_enabled) {
+ int func;
+
+ trace_swap_gd();
+ add_ftrace(func_ptr, caller, FUNCF_ENTRY);
+ func = func_ptr_to_num(func_ptr);
+ if (func < hdr->func_count) {
+ hdr->call_accum[func]++;
+ hdr->call_count++;
+ } else {
+ hdr->untracked_count++;
+ }
+ hdr->depth++;
+ if (hdr->depth > hdr->depth_limit)
+ hdr->max_depth = hdr->depth;
+ trace_swap_gd();
+ }
+}
+
+/**
+ * This is called on every function exit
+ *
+ * We do nothing here.
+ *
+ * @param func_ptr Pointer to function being entered
+ * @param caller Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_exit(
+ void *func_ptr, void *caller)
+{
+ if (trace_enabled) {
+ trace_swap_gd();
+ add_ftrace(func_ptr, caller, FUNCF_EXIT);
+ hdr->depth--;
+ trace_swap_gd();
+ }
+}
+
+/**
+ * Produce a list of called functions
+ *
+ * The information is written into the supplied buffer - a header followed
+ * by a list of function records.
+ *
+ * @param buff Buffer to place list into
+ * @param buff_size Size of buffer
+ * @param needed Returns size of buffer needed, which may be
+ * greater than buff_size if we ran out of space.
+ * @return 0 if ok, -1 if space was exhausted
+ */
+int trace_list_functions(void *buff, size_t buff_size, size_t *needed)
+{
+ struct trace_output_hdr *output_hdr = NULL;
+ void *end, *ptr = buff;
+ size_t func;
+ size_t upto;
+
+ end = buff ? buff + buff_size : NULL;
+
+ /* Place some header information */
+ if (ptr + sizeof(struct trace_output_hdr) < end)
+ output_hdr = ptr;
+ ptr += sizeof(struct trace_output_hdr);
+
+ /* Add information about each function */
+ for (func = upto = 0; func < hdr->func_count; func++) {
+ size_t calls = hdr->call_accum[func];
+
+ if (!calls)
+ continue;
+
+ if (ptr + sizeof(struct trace_output_func) < end) {
+ struct trace_output_func *stats = ptr;
+
+ stats->offset = func * FUNC_SITE_SIZE;
+ stats->call_count = calls;
+ upto++;
+ }
+ ptr += sizeof(struct trace_output_func);
+ }
+
+ /* Update the header */
+ if (output_hdr) {
+ output_hdr->rec_count = upto;
+ output_hdr->type = TRACE_CHUNK_FUNCS;
+ }
+
+ /* Work out how must of the buffer we used */
+ *needed = ptr - buff;
+ if (ptr > end)
+ return -ENOSPC;
+
+ return 0;
+}
+
+int trace_list_calls(void *buff, size_t buff_size, size_t *needed)
+{
+ struct trace_output_hdr *output_hdr = NULL;
+ void *end, *ptr = buff;
+ size_t rec, upto;
+ size_t count;
+
+ end = buff ? buff + buff_size : NULL;
+
+ /* Place some header information */
+ if (ptr + sizeof(struct trace_output_hdr) < end)
+ output_hdr = ptr;
+ ptr += sizeof(struct trace_output_hdr);
+
+ /* Add information about each call */
+ count = hdr->ftrace_count;
+ if (count > hdr->ftrace_size)
+ count = hdr->ftrace_size;
+ for (rec = upto = 0; rec < count; rec++) {
+ if (ptr + sizeof(struct trace_call) < end) {
+ struct trace_call *call = &hdr->ftrace[rec];
+ struct trace_call *out = ptr;
+
+ out->func = call->func * FUNC_SITE_SIZE;
+ out->caller = call->caller * FUNC_SITE_SIZE;
+ out->flags = call->flags;
+ upto++;
+ }
+ ptr += sizeof(struct trace_call);
+ }
+
+ /* Update the header */
+ if (output_hdr) {
+ output_hdr->rec_count = upto;
+ output_hdr->type = TRACE_CHUNK_CALLS;
+ }
+
+ /* Work out how must of the buffer we used */
+ *needed = ptr - buff;
+ if (ptr > end)
+ return -ENOSPC;
+
+ return 0;
+}
+
+/* Print basic information about tracing */
+void trace_print_stats(void)
+{
+ ulong count;
+
+#ifndef FTRACE
+ puts("Warning: make U-Boot with FTRACE to enable function instrumenting.\n");
+ puts("You will likely get zeroed data here\n");
+#endif
+ if (!trace_inited) {
+ printf("Trace is disabled\n");
+ return;
+ }
+ print_grouped_ull(hdr->func_count, 10);
+ puts(" function sites\n");
+ print_grouped_ull(hdr->call_count, 10);
+ puts(" function calls\n");
+ print_grouped_ull(hdr->untracked_count, 10);
+ puts(" untracked function calls\n");
+ count = min(hdr->ftrace_count, hdr->ftrace_size);
+ print_grouped_ull(count, 10);
+ puts(" traced function calls");
+ if (hdr->ftrace_count > hdr->ftrace_size) {
+ printf(" (%lu dropped due to overflow)",
+ hdr->ftrace_count - hdr->ftrace_size);
+ }
+ puts("\n");
+ printf("%15d maximum observed call depth\n", hdr->max_depth);
+ printf("%15d call depth limit\n", hdr->depth_limit);
+ print_grouped_ull(hdr->ftrace_too_deep_count, 10);
+ puts(" calls not traced due to depth\n");
+}
+
+void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
+{
+ trace_enabled = enabled != 0;
+}
+
+/**
+ * Init the tracing system ready for used, and enable it
+ *
+ * @param buff Pointer to trace buffer
+ * @param buff_size Size of trace buffer
+ */
+int __attribute__((no_instrument_function)) trace_init(void *buff,
+ size_t buff_size)
+{
+ ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+ size_t needed;
+ int was_disabled = !trace_enabled;
+
+ trace_save_gd();
+
+ if (!was_disabled) {
+#ifdef CONFIG_TRACE_EARLY
+ char *end;
+ ulong used;
+
+ /*
+ * Copy over the early trace data if we have it. Disable
+ * tracing while we are doing this.
+ */
+ trace_enabled = 0;
+ hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR,
+ CONFIG_TRACE_EARLY_SIZE);
+ end = (char *)&hdr->ftrace[min(hdr->ftrace_count,
+ hdr->ftrace_size)];
+ used = end - (char *)hdr;
+ printf("trace: copying %08lx bytes of early data from %x to %08lx\n",
+ used, CONFIG_TRACE_EARLY_ADDR,
+ (ulong)map_to_sysmem(buff));
+ memcpy(buff, hdr, used);
+#else
+ puts("trace: already enabled\n");
+ return -EALREADY;
+#endif
+ }
+ hdr = (struct trace_hdr *)buff;
+ needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+ if (needed > buff_size) {
+ printf("trace: buffer size %zd bytes: at least %zd needed\n",
+ buff_size, needed);
+ return -ENOSPC;
+ }
+
+ if (was_disabled)
+ memset(hdr, '\0', needed);
+ hdr->func_count = func_count;
+ hdr->call_accum = (uintptr_t *)(hdr + 1);
+
+ /* Use any remaining space for the timed function trace */
+ hdr->ftrace = (struct trace_call *)(buff + needed);
+ hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+ add_textbase();
+
+ puts("trace: enabled\n");
+ hdr->depth_limit = CONFIG_TRACE_CALL_DEPTH_LIMIT;
+ trace_enabled = 1;
+ trace_inited = 1;
+
+ return 0;
+}
+
+#ifdef CONFIG_TRACE_EARLY
+int __attribute__((no_instrument_function)) trace_early_init(void)
+{
+ ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+ size_t buff_size = CONFIG_TRACE_EARLY_SIZE;
+ size_t needed;
+
+ /* We can ignore additional calls to this function */
+ if (trace_enabled)
+ return 0;
+
+ hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR, CONFIG_TRACE_EARLY_SIZE);
+ needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+ if (needed > buff_size) {
+ printf("trace: buffer size is %zd bytes, at least %zd needed\n",
+ buff_size, needed);
+ return -ENOSPC;
+ }
+
+ memset(hdr, '\0', needed);
+ hdr->call_accum = (uintptr_t *)(hdr + 1);
+ hdr->func_count = func_count;
+
+ /* Use any remaining space for the timed function trace */
+ hdr->ftrace = (struct trace_call *)((char *)hdr + needed);
+ hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+ add_textbase();
+ hdr->depth_limit = CONFIG_TRACE_EARLY_CALL_DEPTH_LIMIT;
+ printf("trace: early enable at %08x\n", CONFIG_TRACE_EARLY_ADDR);
+
+ trace_enabled = 1;
+
+ return 0;
+}
+#endif
diff --git a/lib/uuid.c b/lib/uuid.c
new file mode 100644
index 00000000..db768a25
--- /dev/null
+++ b/lib/uuid.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2011 Calxeda, Inc.
+ */
+
+#include <common.h>
+#include <env.h>
+#include <time.h>
+#include <linux/ctype.h>
+#include <errno.h>
+#include <common.h>
+#include <asm/io.h>
+#include <part_efi.h>
+#include <malloc.h>
+
+/*
+ * UUID - Universally Unique IDentifier - 128 bits unique number.
+ * There are 5 versions and one variant of UUID defined by RFC4122
+ * specification. A UUID contains a set of fields. The set varies
+ * depending on the version of the UUID, as shown below:
+ * - time, MAC address(v1),
+ * - user ID(v2),
+ * - MD5 of name or URL(v3),
+ * - random data(v4),
+ * - SHA-1 of name or URL(v5),
+ *
+ * Layout of UUID:
+ * timestamp - 60-bit: time_low, time_mid, time_hi_and_version
+ * version - 4 bit (bit 4 through 7 of the time_hi_and_version)
+ * clock seq - 14 bit: clock_seq_hi_and_reserved, clock_seq_low
+ * variant: - bit 6 and 7 of clock_seq_hi_and_reserved
+ * node - 48 bit
+ *
+ * source: https://www.ietf.org/rfc/rfc4122.txt
+ *
+ * UUID binary format (16 bytes):
+ *
+ * 4B-2B-2B-2B-6B (big endian - network byte order)
+ *
+ * UUID string is 36 length of characters (36 bytes):
+ *
+ * 0 9 14 19 24
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be be be be be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, le means the field should be converted
+ * to little endian and be means it should be converted to big endian.
+ *
+ * UUID is also used as GUID (Globally Unique Identifier) with the same binary
+ * format but it differs in string format like below.
+ *
+ * GUID:
+ * 0 9 14 19 24
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * le le le be be
+ *
+ * GUID is used e.g. in GPT (GUID Partition Table) as a partiions unique id.
+ */
+int uuid_str_valid(const char *uuid)
+{
+ int i, valid;
+
+ if (uuid == NULL)
+ return 0;
+
+ for (i = 0, valid = 1; uuid[i] && valid; i++) {
+ switch (i) {
+ case 8: case 13: case 18: case 23:
+ valid = (uuid[i] == '-');
+ break;
+ default:
+ valid = isxdigit(uuid[i]);
+ break;
+ }
+ }
+
+ if (i != UUID_STR_LEN || !valid)
+ return 0;
+
+ return 1;
+}
+
+#ifdef CONFIG_PARTITION_TYPE_GUID
+static const struct {
+ const char *string;
+ efi_guid_t guid;
+} list_guid[] = {
+ {"system", PARTITION_SYSTEM_GUID},
+ {"mbr", LEGACY_MBR_PARTITION_GUID},
+ {"msft", PARTITION_MSFT_RESERVED_GUID},
+ {"data", PARTITION_BASIC_DATA_GUID},
+ {"linux", PARTITION_LINUX_FILE_SYSTEM_DATA_GUID},
+ {"home", PARTITION_HOME_GUID},
+ {"boot", PARTITION_EXTENDED_BOOT_GUID},
+ {"raid", PARTITION_LINUX_RAID_GUID},
+ {"swap", PARTITION_LINUX_SWAP_GUID},
+ {"lvm", PARTITION_LINUX_LVM_GUID}
+};
+
+/*
+ * uuid_guid_get_bin() - this function get GUID bin for string
+ *
+ * @param guid_str - pointer to partition type string
+ * @param guid_bin - pointer to allocated array for big endian output [16B]
+ */
+int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
+ if (!strcmp(list_guid[i].string, guid_str)) {
+ memcpy(guid_bin, &list_guid[i].guid, 16);
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+/*
+ * uuid_guid_get_str() - this function get string for GUID.
+ *
+ * @param guid_bin - pointer to string with partition type guid [16B]
+ * @param guid_str - pointer to allocated partition type string [7B]
+ */
+int uuid_guid_get_str(unsigned char *guid_bin, char *guid_str)
+{
+ int i;
+
+ *guid_str = 0;
+ for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
+ if (!memcmp(list_guid[i].guid.b, guid_bin, 16)) {
+ strcpy(guid_str, list_guid[i].string);
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+#endif
+
+/*
+ * uuid_str_to_bin() - convert string UUID or GUID to big endian binary data.
+ *
+ * @param uuid_str - pointer to UUID or GUID string [37B] or GUID shorcut
+ * @param uuid_bin - pointer to allocated array for big endian output [16B]
+ * @str_format - UUID string format: 0 - UUID; 1 - GUID
+ */
+int uuid_str_to_bin(char *uuid_str, unsigned char *uuid_bin, int str_format)
+{
+ uint16_t tmp16;
+ uint32_t tmp32;
+ uint64_t tmp64;
+
+ if (!uuid_str_valid(uuid_str)) {
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ if (!uuid_guid_get_bin(uuid_str, uuid_bin))
+ return 0;
+#endif
+ return -EINVAL;
+ }
+
+ if (str_format == UUID_STR_FORMAT_STD) {
+ tmp32 = cpu_to_be32(simple_strtoul(uuid_str, NULL, 16));
+ memcpy(uuid_bin, &tmp32, 4);
+
+ tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 9, NULL, 16));
+ memcpy(uuid_bin + 4, &tmp16, 2);
+
+ tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 14, NULL, 16));
+ memcpy(uuid_bin + 6, &tmp16, 2);
+ } else {
+ tmp32 = cpu_to_le32(simple_strtoul(uuid_str, NULL, 16));
+ memcpy(uuid_bin, &tmp32, 4);
+
+ tmp16 = cpu_to_le16(simple_strtoul(uuid_str + 9, NULL, 16));
+ memcpy(uuid_bin + 4, &tmp16, 2);
+
+ tmp16 = cpu_to_le16(simple_strtoul(uuid_str + 14, NULL, 16));
+ memcpy(uuid_bin + 6, &tmp16, 2);
+ }
+
+ tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 19, NULL, 16));
+ memcpy(uuid_bin + 8, &tmp16, 2);
+
+ tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16));
+ memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6);
+
+ return 0;
+}
+
+/*
+ * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
+ *
+ * @param uuid_bin: pointer to binary data of UUID (big endian) [16B]
+ * @param uuid_str: pointer to allocated array for output string [37B]
+ * @str_format: bit 0: 0 - UUID; 1 - GUID
+ * bit 1: 0 - lower case; 2 - upper case
+ */
+void uuid_bin_to_str(unsigned char *uuid_bin, char *uuid_str, int str_format)
+{
+ const u8 uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15};
+ const u8 guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8,
+ 9, 10, 11, 12, 13, 14, 15};
+ const u8 *char_order;
+ const char *format;
+ int i;
+
+ /*
+ * UUID and GUID bin data - always in big endian:
+ * 4B-2B-2B-2B-6B
+ * be be be be be
+ */
+ if (str_format & UUID_STR_FORMAT_GUID)
+ char_order = guid_char_order;
+ else
+ char_order = uuid_char_order;
+ if (str_format & UUID_STR_UPPER_CASE)
+ format = "%02X";
+ else
+ format = "%02x";
+
+ for (i = 0; i < 16; i++) {
+ sprintf(uuid_str, format, uuid_bin[char_order[i]]);
+ uuid_str += 2;
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ *uuid_str++ = '-';
+ break;
+ }
+ }
+}
+
+/*
+ * gen_rand_uuid() - this function generates a random binary UUID version 4.
+ * In this version all fields beside 4 bits of version and
+ * 2 bits of variant are randomly generated.
+ *
+ * @param uuid_bin - pointer to allocated array [16B]. Output is in big endian.
+*/
+#if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
+void gen_rand_uuid(unsigned char *uuid_bin)
+{
+ u32 ptr[4];
+ struct uuid *uuid = (struct uuid *)ptr;
+ int i;
+
+ srand(get_ticks() + rand());
+
+ /* Set all fields randomly */
+ for (i = 0; i < 4; i++)
+ ptr[i] = rand();
+
+ clrsetbits_be16(&uuid->time_hi_and_version,
+ UUID_VERSION_MASK,
+ UUID_VERSION << UUID_VERSION_SHIFT);
+
+ clrsetbits_8(&uuid->clock_seq_hi_and_reserved,
+ UUID_VARIANT_MASK,
+ UUID_VARIANT << UUID_VARIANT_SHIFT);
+
+ memcpy(uuid_bin, uuid, 16);
+}
+
+/*
+ * gen_rand_uuid_str() - this function generates UUID v4 (random) in two string
+ * formats UUID or GUID.
+ *
+ * @param uuid_str - pointer to allocated array [37B].
+ * @param - uuid output type: UUID - 0, GUID - 1
+ */
+void gen_rand_uuid_str(char *uuid_str, int str_format)
+{
+ unsigned char uuid_bin[UUID_BIN_LEN];
+
+ /* Generate UUID (big endian) */
+ gen_rand_uuid(uuid_bin);
+
+ /* Convert UUID bin to UUID or GUID formated STRING */
+ uuid_bin_to_str(uuid_bin, uuid_str, str_format);
+}
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID)
+int do_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ char uuid[UUID_STR_LEN + 1];
+ int str_format;
+
+ if (!strcmp(argv[0], "uuid"))
+ str_format = UUID_STR_FORMAT_STD;
+ else
+ str_format = UUID_STR_FORMAT_GUID;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ gen_rand_uuid_str(uuid, str_format);
+
+ if (argc == 1)
+ printf("%s\n", uuid);
+ else
+ env_set(argv[1], uuid);
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(uuid, CONFIG_SYS_MAXARGS, 1, do_uuid,
+ "UUID - generate random Universally Unique Identifier",
+ "[<varname>]\n"
+ "Argument:\n"
+ "varname: for set result in a environment variable\n"
+ "e.g. uuid uuid_env"
+);
+
+U_BOOT_CMD(guid, CONFIG_SYS_MAXARGS, 1, do_uuid,
+ "GUID - generate Globally Unique Identifier based on random UUID",
+ "[<varname>]\n"
+ "Argument:\n"
+ "varname: for set result in a environment variable\n"
+ "e.g. guid guid_env"
+);
+#endif /* CONFIG_CMD_UUID */
+#endif /* CONFIG_RANDOM_UUID || CONFIG_CMD_UUID */
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
new file mode 100644
index 00000000..b4edee29
--- /dev/null
+++ b/lib/vsprintf.c
@@ -0,0 +1,890 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ *
+ * from hush: simple_itoa() was lifted from boa-0.93.15
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <efi_loader.h>
+#include <div64.h>
+#include <hexdump.h>
+#include <stdarg.h>
+#include <vsprintf.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#define noinline __attribute__((noinline))
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+ int i = 0;
+
+ while (is_digit(**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 noinline char *put_dec(char *buf, uint64_t 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 /* Must be 32 == 0x20 */
+#define SPECIAL 64 /* 0x */
+
+/*
+ * Macro to add a new character to our output string, but only if it will
+ * fit. The macro moves to the next character position in the output string.
+ */
+#define ADDCH(str, ch) do { \
+ if ((str) < end) \
+ *(str) = (ch); \
+ ++str; \
+ } while (0)
+
+static char *number(char *buf, char *end, u64 num,
+ int base, int size, int precision, int type)
+{
+ /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
+ static const char digits[16] = "0123456789ABCDEF";
+
+ char tmp[66];
+ char sign;
+ char locase;
+ int need_pfx = ((type & SPECIAL) && base != 10);
+ int i;
+
+ /* locase = 0 or 0x20. ORing digits or letters with 'locase'
+ * produces same digits or (maybe lowercased) letters */
+ locase = (type & SMALL);
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ sign = 0;
+ if (type & SIGN) {
+ if ((s64) num < 0) {
+ sign = '-';
+ num = -(s64) num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (need_pfx) {
+ size--;
+ if (base == 16)
+ size--;
+ }
+
+ /* 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 (base != 10) { /* 8 or 16 */
+ int mask = base - 1;
+ int shift = 3;
+
+ if (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 > precision)
+ precision = i;
+ /* leading space padding */
+ size -= precision;
+ if (!(type & (ZEROPAD + LEFT))) {
+ while (--size >= 0)
+ ADDCH(buf, ' ');
+ }
+ /* sign */
+ if (sign)
+ ADDCH(buf, sign);
+ /* "0x" / "0" prefix */
+ if (need_pfx) {
+ ADDCH(buf, '0');
+ if (base == 16)
+ ADDCH(buf, 'X' | locase);
+ }
+ /* zero or space padding */
+ if (!(type & LEFT)) {
+ char c = (type & ZEROPAD) ? '0' : ' ';
+
+ while (--size >= 0)
+ ADDCH(buf, c);
+ }
+ /* hmm even more zero padding? */
+ while (i <= --precision)
+ ADDCH(buf, '0');
+ /* actual digits of result */
+ while (--i >= 0)
+ ADDCH(buf, tmp[i]);
+ /* trailing space padding */
+ while (--size >= 0)
+ ADDCH(buf, ' ');
+ return buf;
+}
+
+static char *string(char *buf, char *end, char *s, int field_width,
+ int precision, int flags)
+{
+ int len, i;
+
+ if (s == NULL)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ ADDCH(buf, ' ');
+ for (i = 0; i < len; ++i)
+ ADDCH(buf, *s++);
+ while (len < field_width--)
+ ADDCH(buf, ' ');
+ return buf;
+}
+
+/* U-Boot uses UTF-16 strings in the EFI context only. */
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
+static char *string16(char *buf, char *end, u16 *s, int field_width,
+ int precision, int flags)
+{
+ const u16 *str = s ? s : L"<NULL>";
+ ssize_t i, len = utf16_strnlen(str, precision);
+
+ if (!(flags & LEFT))
+ for (; len < field_width; --field_width)
+ ADDCH(buf, ' ');
+ for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) {
+ s32 s = utf16_get(&str);
+
+ if (s < 0)
+ s = '?';
+ utf8_put(s, &buf);
+ }
+ for (; len < field_width; --field_width)
+ ADDCH(buf, ' ');
+ return buf;
+}
+
+#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT)
+static char *device_path_string(char *buf, char *end, void *dp, int field_width,
+ int precision, int flags)
+{
+ u16 *str;
+
+ /* If dp == NULL output the string '<NULL>' */
+ if (!dp)
+ return string16(buf, end, dp, field_width, precision, flags);
+
+ str = efi_dp_str((struct efi_device_path *)dp);
+ if (!str)
+ return ERR_PTR(-ENOMEM);
+
+ buf = string16(buf, end, str, field_width, precision, flags);
+ efi_free_pool(str);
+ return buf;
+}
+#endif
+#endif
+
+static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
+ int precision, int flags)
+{
+ /* (6 * 2 hex digits), 5 colons and trailing zero */
+ char mac_addr[6 * 3];
+ char *p = mac_addr;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ p = hex_byte_pack(p, addr[i]);
+ if (!(flags & SPECIAL) && i != 5)
+ *p++ = ':';
+ }
+ *p = '\0';
+
+ return string(buf, end, mac_addr, field_width, precision,
+ flags & ~SPECIAL);
+}
+
+static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
+ int precision, int flags)
+{
+ /* (8 * 4 hex digits), 7 colons and trailing zero */
+ char ip6_addr[8 * 5];
+ char *p = ip6_addr;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ p = hex_byte_pack(p, addr[2 * i]);
+ p = hex_byte_pack(p, addr[2 * i + 1]);
+ if (!(flags & SPECIAL) && i != 7)
+ *p++ = ':';
+ }
+ *p = '\0';
+
+ return string(buf, end, ip6_addr, field_width, precision,
+ flags & ~SPECIAL);
+}
+
+static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
+ int precision, int flags)
+{
+ /* (4 * 3 decimal digits), 3 dots and trailing zero */
+ char ip4_addr[4 * 4];
+ char temp[3]; /* hold each IP quad in reverse order */
+ char *p = ip4_addr;
+ int i, digits;
+
+ for (i = 0; i < 4; i++) {
+ digits = put_dec_trunc(temp, addr[i]) - temp;
+ /* reverse the digits in the quad */
+ while (digits--)
+ *p++ = temp[digits];
+ if (i != 3)
+ *p++ = '.';
+ }
+ *p = '\0';
+
+ return string(buf, end, ip4_addr, field_width, precision,
+ flags & ~SPECIAL);
+}
+
+#ifdef CONFIG_LIB_UUID
+/*
+ * This works (roughly) the same way as Linux's.
+ *
+ * %pUb: 01020304-0506-0708-090a-0b0c0d0e0f10
+ * %pUB: 01020304-0506-0708-090A-0B0C0D0E0F10
+ * %pUl: 04030201-0605-0807-090a-0b0c0d0e0f10
+ * %pUL: 04030201-0605-0807-090A-0B0C0D0E0F10
+ */
+static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
+ int precision, int flags, const char *fmt)
+{
+ char uuid[UUID_STR_LEN + 1];
+ int str_format;
+
+ switch (*(++fmt)) {
+ case 'L':
+ str_format = UUID_STR_FORMAT_GUID | UUID_STR_UPPER_CASE;
+ break;
+ case 'l':
+ str_format = UUID_STR_FORMAT_GUID;
+ break;
+ case 'B':
+ str_format = UUID_STR_FORMAT_STD | UUID_STR_UPPER_CASE;
+ break;
+ default:
+ str_format = UUID_STR_FORMAT_STD;
+ break;
+ }
+
+ if (addr)
+ uuid_bin_to_str(addr, uuid, str_format);
+ else
+ strcpy(uuid, "<NULL>");
+
+ return string(buf, end, uuid, field_width, precision, flags);
+}
+#endif
+
+/*
+ * 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:
+ *
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+ * usual colon-separated hex notation
+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
+ * decimal for v4 and colon separated network-order 16 bit hex for v6)
+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
+ * currently the same
+ *
+ * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
+ * function pointers are really function descriptors, which contain a
+ * pointer to the real address.
+ */
+static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+ int field_width, int precision, int flags)
+{
+ u64 num = (uintptr_t)ptr;
+
+ /*
+ * Being a boot loader, we explicitly allow pointers to
+ * (physical) address null.
+ */
+#if 0
+ if (!ptr)
+ return string(buf, end, "(null)", field_width, precision,
+ flags);
+#endif
+
+ switch (*fmt) {
+/* Device paths only exist in the EFI context. */
+#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) && !defined(API_BUILD)
+ case 'D':
+ return device_path_string(buf, end, ptr, field_width,
+ precision, flags);
+#endif
+ case 'a':
+ flags |= SPECIAL | ZEROPAD;
+
+ switch (fmt[1]) {
+ case 'p':
+ default:
+ field_width = sizeof(phys_addr_t) * 2 + 2;
+ num = *(phys_addr_t *)ptr;
+ break;
+ }
+ break;
+ case 'm':
+ flags |= SPECIAL;
+ /* Fallthrough */
+ case 'M':
+ return mac_address_string(buf, end, ptr, field_width,
+ precision, flags);
+ case 'i':
+ flags |= SPECIAL;
+ /* Fallthrough */
+ case 'I':
+ if (fmt[1] == '6')
+ return ip6_addr_string(buf, end, ptr, field_width,
+ precision, flags);
+ if (fmt[1] == '4')
+ return ip4_addr_string(buf, end, ptr, field_width,
+ precision, flags);
+ flags &= ~SPECIAL;
+ break;
+#ifdef CONFIG_LIB_UUID
+ case 'U':
+ return uuid_string(buf, end, ptr, field_width, precision,
+ flags, fmt);
+#endif
+ default:
+ break;
+ }
+ flags |= SMALL;
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ return number(buf, end, num, 16, field_width, precision, flags);
+}
+
+static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
+ va_list args)
+{
+ u64 num;
+ int base;
+ char *str;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* '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 */
+ char *end = buf + size;
+
+ /* Make sure end is always >= buf - do we want this in U-Boot? */
+ if (end < buf) {
+ end = ((void *)-1);
+ size = end - buf;
+ }
+ str = buf;
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ ADDCH(str, *fmt);
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-':
+ flags |= LEFT;
+ goto repeat;
+ case '+':
+ flags |= PLUS;
+ goto repeat;
+ case ' ':
+ flags |= SPACE;
+ goto repeat;
+ case '#':
+ flags |= SPECIAL;
+ goto repeat;
+ case '0':
+ flags |= ZEROPAD;
+ goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (is_digit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (is_digit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
+ qualifier = *fmt;
+ ++fmt;
+ if (qualifier == 'l' && *fmt == 'l') {
+ qualifier = 'L';
+ ++fmt;
+ }
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0)
+ ADDCH(str, ' ');
+ }
+ ADDCH(str, (unsigned char) va_arg(args, int));
+ while (--field_width > 0)
+ ADDCH(str, ' ');
+ continue;
+
+ case 's':
+/* U-Boot uses UTF-16 strings in the EFI context only. */
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
+ if (qualifier == 'l') {
+ str = string16(str, end, va_arg(args, u16 *),
+ field_width, precision, flags);
+ } else
+#endif
+ {
+ str = string(str, end, va_arg(args, char *),
+ field_width, precision, flags);
+ }
+ continue;
+
+ case 'p':
+ str = pointer(fmt + 1, str, end,
+ va_arg(args, void *),
+ field_width, precision, flags);
+ if (IS_ERR(str))
+ return PTR_ERR(str);
+ /* Skip all alphanumeric pointer suffixes */
+ while (isalnum(fmt[1]))
+ fmt++;
+ continue;
+
+ case 'n':
+ if (qualifier == 'l') {
+ long *ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int *ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ ADDCH(str, '%');
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'x':
+ flags |= SMALL;
+ case 'X':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ ADDCH(str, '%');
+ if (*fmt)
+ ADDCH(str, *fmt);
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'L') /* "quad" for 64 bit variables */
+ num = va_arg(args, unsigned long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z' || qualifier == 'z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 't') {
+ num = va_arg(args, ptrdiff_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+ str = number(str, end, num, base, field_width, precision,
+ flags);
+ }
+
+ if (size > 0) {
+ ADDCH(str, '\0');
+ if (str > end)
+ end[-1] = '\0';
+ --str;
+ }
+ /* the trailing null byte doesn't count towards the total */
+ return str - buf;
+}
+
+int vsnprintf(char *buf, size_t size, const char *fmt,
+ va_list args)
+{
+ return vsnprintf_internal(buf, size, fmt, args);
+}
+
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int i;
+
+ i = vsnprintf(buf, size, fmt, args);
+
+ if (likely(i < size))
+ return i;
+ if (size != 0)
+ return size - 1;
+ return 0;
+}
+
+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;
+}
+
+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;
+}
+
+/**
+ * Format a string and place it in a buffer (va_list version)
+ *
+ * @param buf The buffer to place the result into
+ * @param fmt The format string to use
+ * @param 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.
+ *
+ * If you're not already dealing with a va_list consider using sprintf().
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf_internal(buf, INT_MAX, fmt, args);
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsprintf(buf, fmt, args);
+ va_end(args);
+ return i;
+}
+
+#if CONFIG_IS_ENABLED(PRINTF)
+int printf(const char *fmt, ...)
+{
+ va_list args;
+ uint i;
+ char printbuffer[CONFIG_SYS_PBSIZE];
+
+ va_start(args, fmt);
+
+ /*
+ * For this to work, printbuffer must be larger than
+ * anything we ever want to print.
+ */
+ i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+ va_end(args);
+
+ /* Handle error */
+ if (i <= 0)
+ return i;
+ /* Print the string */
+ puts(printbuffer);
+ return i;
+}
+
+int vprintf(const char *fmt, va_list args)
+{
+ uint i;
+ char printbuffer[CONFIG_SYS_PBSIZE];
+
+ /*
+ * For this to work, printbuffer must be larger than
+ * anything we ever want to print.
+ */
+ i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+
+ /* Handle error */
+ if (i <= 0)
+ return i;
+ /* Print the string */
+ puts(printbuffer);
+ return i;
+}
+#endif
+
+char *simple_itoa(ulong i)
+{
+ /* 21 digits plus null terminator, good for 64-bit or smaller ints */
+ static char local[22];
+ char *p = &local[21];
+
+ *p-- = '\0';
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+}
+
+/* We don't seem to have %'d in U-Boot */
+void print_grouped_ull(unsigned long long int_val, int digits)
+{
+ char str[21], *s;
+ int grab = 3;
+
+ digits = (digits + 2) / 3;
+ sprintf(str, "%*llu", digits * 3, int_val);
+ for (s = str; *s; s += grab) {
+ if (s != str)
+ putc(s[-1] != ' ' ? ',' : ' ');
+ printf("%.*s", grab, s);
+ grab = 3;
+ }
+}
+
+bool str2off(const char *p, loff_t *num)
+{
+ char *endptr;
+
+ *num = simple_strtoull(p, &endptr, 16);
+ return *p != '\0' && *endptr == '\0';
+}
+
+bool str2long(const char *p, ulong *num)
+{
+ char *endptr;
+
+ *num = simple_strtoul(p, &endptr, 16);
+ return *p != '\0' && *endptr == '\0';
+}
+
+char *strmhz(char *buf, unsigned long hz)
+{
+ long l, n;
+ long m;
+
+ n = DIV_ROUND_CLOSEST(hz, 1000) / 1000L;
+ l = sprintf(buf, "%ld", n);
+
+ hz -= n * 1000000L;
+ m = DIV_ROUND_CLOSEST(hz, 1000L);
+ if (m != 0)
+ sprintf(buf + l, ".%03ld", m);
+
+ return buf;
+}
diff --git a/lib/xxhash.c b/lib/xxhash.c
new file mode 100644
index 00000000..2fb4dc6d
--- /dev/null
+++ b/lib/xxhash.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
+/*
+ * xxHash - Extremely Fast Hash algorithm
+ * Copyright (C) 2012-2016, Yann Collet.
+ *
+ * You can contact the author at:
+ * - xxHash homepage: http://cyan4973.github.io/xxHash/
+ * - xxHash source repository: https://github.com/Cyan4973/xxHash
+ */
+
+#include <asm/unaligned.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/compat.h>
+#include <linux/string.h>
+#include <linux/xxhash.h>
+
+/*-*************************************
+ * Macros
+ **************************************/
+#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r)))
+#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r)))
+
+#ifdef __LITTLE_ENDIAN
+# define XXH_CPU_LITTLE_ENDIAN 1
+#else
+# define XXH_CPU_LITTLE_ENDIAN 0
+#endif
+
+/*-*************************************
+ * Constants
+ **************************************/
+static const uint32_t PRIME32_1 = 2654435761U;
+static const uint32_t PRIME32_2 = 2246822519U;
+static const uint32_t PRIME32_3 = 3266489917U;
+static const uint32_t PRIME32_4 = 668265263U;
+static const uint32_t PRIME32_5 = 374761393U;
+
+static const uint64_t PRIME64_1 = 11400714785074694791ULL;
+static const uint64_t PRIME64_2 = 14029467366897019727ULL;
+static const uint64_t PRIME64_3 = 1609587929392839161ULL;
+static const uint64_t PRIME64_4 = 9650029242287828579ULL;
+static const uint64_t PRIME64_5 = 2870177450012600261ULL;
+
+/*-**************************
+ * Utils
+ ***************************/
+void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+EXPORT_SYMBOL(xxh32_copy_state);
+
+void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+EXPORT_SYMBOL(xxh64_copy_state);
+
+/*-***************************
+ * Simple Hash Functions
+ ****************************/
+static uint32_t xxh32_round(uint32_t seed, const uint32_t input)
+{
+ seed += input * PRIME32_2;
+ seed = xxh_rotl32(seed, 13);
+ seed *= PRIME32_1;
+ return seed;
+}
+
+uint32_t xxh32(const void *input, const size_t len, const uint32_t seed)
+{
+ const uint8_t *p = (const uint8_t *)input;
+ const uint8_t *b_end = p + len;
+ uint32_t h32;
+
+ if (len >= 16) {
+ const uint8_t *const limit = b_end - 16;
+ uint32_t v1 = seed + PRIME32_1 + PRIME32_2;
+ uint32_t v2 = seed + PRIME32_2;
+ uint32_t v3 = seed + 0;
+ uint32_t v4 = seed - PRIME32_1;
+
+ do {
+ v1 = xxh32_round(v1, get_unaligned_le32(p));
+ p += 4;
+ v2 = xxh32_round(v2, get_unaligned_le32(p));
+ p += 4;
+ v3 = xxh32_round(v3, get_unaligned_le32(p));
+ p += 4;
+ v4 = xxh32_round(v4, get_unaligned_le32(p));
+ p += 4;
+ } while (p <= limit);
+
+ h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) +
+ xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18);
+ } else {
+ h32 = seed + PRIME32_5;
+ }
+
+ h32 += (uint32_t)len;
+
+ while (p + 4 <= b_end) {
+ h32 += get_unaligned_le32(p) * PRIME32_3;
+ h32 = xxh_rotl32(h32, 17) * PRIME32_4;
+ p += 4;
+ }
+
+ while (p < b_end) {
+ h32 += (*p) * PRIME32_5;
+ h32 = xxh_rotl32(h32, 11) * PRIME32_1;
+ p++;
+ }
+
+ h32 ^= h32 >> 15;
+ h32 *= PRIME32_2;
+ h32 ^= h32 >> 13;
+ h32 *= PRIME32_3;
+ h32 ^= h32 >> 16;
+
+ return h32;
+}
+EXPORT_SYMBOL(xxh32);
+
+static uint64_t xxh64_round(uint64_t acc, const uint64_t input)
+{
+ acc += input * PRIME64_2;
+ acc = xxh_rotl64(acc, 31);
+ acc *= PRIME64_1;
+ return acc;
+}
+
+static uint64_t xxh64_merge_round(uint64_t acc, uint64_t val)
+{
+ val = xxh64_round(0, val);
+ acc ^= val;
+ acc = acc * PRIME64_1 + PRIME64_4;
+ return acc;
+}
+
+uint64_t xxh64(const void *input, const size_t len, const uint64_t seed)
+{
+ const uint8_t *p = (const uint8_t *)input;
+ const uint8_t *const b_end = p + len;
+ uint64_t h64;
+
+ if (len >= 32) {
+ const uint8_t *const limit = b_end - 32;
+ uint64_t v1 = seed + PRIME64_1 + PRIME64_2;
+ uint64_t v2 = seed + PRIME64_2;
+ uint64_t v3 = seed + 0;
+ uint64_t v4 = seed - PRIME64_1;
+
+ do {
+ v1 = xxh64_round(v1, get_unaligned_le64(p));
+ p += 8;
+ v2 = xxh64_round(v2, get_unaligned_le64(p));
+ p += 8;
+ v3 = xxh64_round(v3, get_unaligned_le64(p));
+ p += 8;
+ v4 = xxh64_round(v4, get_unaligned_le64(p));
+ p += 8;
+ } while (p <= limit);
+
+ h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
+ xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
+ h64 = xxh64_merge_round(h64, v1);
+ h64 = xxh64_merge_round(h64, v2);
+ h64 = xxh64_merge_round(h64, v3);
+ h64 = xxh64_merge_round(h64, v4);
+
+ } else {
+ h64 = seed + PRIME64_5;
+ }
+
+ h64 += (uint64_t)len;
+
+ while (p + 8 <= b_end) {
+ const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
+
+ h64 ^= k1;
+ h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
+ p += 8;
+ }
+
+ if (p + 4 <= b_end) {
+ h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
+ h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+ p += 4;
+ }
+
+ while (p < b_end) {
+ h64 ^= (*p) * PRIME64_5;
+ h64 = xxh_rotl64(h64, 11) * PRIME64_1;
+ p++;
+ }
+
+ h64 ^= h64 >> 33;
+ h64 *= PRIME64_2;
+ h64 ^= h64 >> 29;
+ h64 *= PRIME64_3;
+ h64 ^= h64 >> 32;
+
+ return h64;
+}
+EXPORT_SYMBOL(xxh64);
+
+/*-**************************************************
+ * Advanced Hash Functions
+ ***************************************************/
+void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed)
+{
+ /* use a local state for memcpy() to avoid strict-aliasing warnings */
+ struct xxh32_state state;
+
+ memset(&state, 0, sizeof(state));
+ state.v1 = seed + PRIME32_1 + PRIME32_2;
+ state.v2 = seed + PRIME32_2;
+ state.v3 = seed + 0;
+ state.v4 = seed - PRIME32_1;
+ memcpy(statePtr, &state, sizeof(state));
+}
+EXPORT_SYMBOL(xxh32_reset);
+
+void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed)
+{
+ /* use a local state for memcpy() to avoid strict-aliasing warnings */
+ struct xxh64_state state;
+
+ memset(&state, 0, sizeof(state));
+ state.v1 = seed + PRIME64_1 + PRIME64_2;
+ state.v2 = seed + PRIME64_2;
+ state.v3 = seed + 0;
+ state.v4 = seed - PRIME64_1;
+ memcpy(statePtr, &state, sizeof(state));
+}
+EXPORT_SYMBOL(xxh64_reset);
+
+int xxh32_update(struct xxh32_state *state, const void *input, const size_t len)
+{
+ const uint8_t *p = (const uint8_t *)input;
+ const uint8_t *const b_end = p + len;
+
+ if (input == NULL)
+ return -EINVAL;
+
+ state->total_len_32 += (uint32_t)len;
+ state->large_len |= (len >= 16) | (state->total_len_32 >= 16);
+
+ if (state->memsize + len < 16) { /* fill in tmp buffer */
+ memcpy((uint8_t *)(state->mem32) + state->memsize, input, len);
+ state->memsize += (uint32_t)len;
+ return 0;
+ }
+
+ if (state->memsize) { /* some data left from previous update */
+ const uint32_t *p32 = state->mem32;
+
+ memcpy((uint8_t *)(state->mem32) + state->memsize, input,
+ 16 - state->memsize);
+
+ state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32));
+ p32++;
+ state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32));
+ p32++;
+ state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32));
+ p32++;
+ state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32));
+ p32++;
+
+ p += 16-state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p <= b_end - 16) {
+ const uint8_t *const limit = b_end - 16;
+ uint32_t v1 = state->v1;
+ uint32_t v2 = state->v2;
+ uint32_t v3 = state->v3;
+ uint32_t v4 = state->v4;
+
+ do {
+ v1 = xxh32_round(v1, get_unaligned_le32(p));
+ p += 4;
+ v2 = xxh32_round(v2, get_unaligned_le32(p));
+ p += 4;
+ v3 = xxh32_round(v3, get_unaligned_le32(p));
+ p += 4;
+ v4 = xxh32_round(v4, get_unaligned_le32(p));
+ p += 4;
+ } while (p <= limit);
+
+ state->v1 = v1;
+ state->v2 = v2;
+ state->v3 = v3;
+ state->v4 = v4;
+ }
+
+ if (p < b_end) {
+ memcpy(state->mem32, p, (size_t)(b_end-p));
+ state->memsize = (uint32_t)(b_end-p);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(xxh32_update);
+
+uint32_t xxh32_digest(const struct xxh32_state *state)
+{
+ const uint8_t *p = (const uint8_t *)state->mem32;
+ const uint8_t *const b_end = (const uint8_t *)(state->mem32) +
+ state->memsize;
+ uint32_t h32;
+
+ if (state->large_len) {
+ h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) +
+ xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18);
+ } else {
+ h32 = state->v3 /* == seed */ + PRIME32_5;
+ }
+
+ h32 += state->total_len_32;
+
+ while (p + 4 <= b_end) {
+ h32 += get_unaligned_le32(p) * PRIME32_3;
+ h32 = xxh_rotl32(h32, 17) * PRIME32_4;
+ p += 4;
+ }
+
+ while (p < b_end) {
+ h32 += (*p) * PRIME32_5;
+ h32 = xxh_rotl32(h32, 11) * PRIME32_1;
+ p++;
+ }
+
+ h32 ^= h32 >> 15;
+ h32 *= PRIME32_2;
+ h32 ^= h32 >> 13;
+ h32 *= PRIME32_3;
+ h32 ^= h32 >> 16;
+
+ return h32;
+}
+EXPORT_SYMBOL(xxh32_digest);
+
+int xxh64_update(struct xxh64_state *state, const void *input, const size_t len)
+{
+ const uint8_t *p = (const uint8_t *)input;
+ const uint8_t *const b_end = p + len;
+
+ if (input == NULL)
+ return -EINVAL;
+
+ state->total_len += len;
+
+ if (state->memsize + len < 32) { /* fill in tmp buffer */
+ memcpy(((uint8_t *)state->mem64) + state->memsize, input, len);
+ state->memsize += (uint32_t)len;
+ return 0;
+ }
+
+ if (state->memsize) { /* tmp buffer is full */
+ uint64_t *p64 = state->mem64;
+
+ memcpy(((uint8_t *)p64) + state->memsize, input,
+ 32 - state->memsize);
+
+ state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64));
+ p64++;
+ state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64));
+ p64++;
+ state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64));
+ p64++;
+ state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64));
+
+ p += 32 - state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p + 32 <= b_end) {
+ const uint8_t *const limit = b_end - 32;
+ uint64_t v1 = state->v1;
+ uint64_t v2 = state->v2;
+ uint64_t v3 = state->v3;
+ uint64_t v4 = state->v4;
+
+ do {
+ v1 = xxh64_round(v1, get_unaligned_le64(p));
+ p += 8;
+ v2 = xxh64_round(v2, get_unaligned_le64(p));
+ p += 8;
+ v3 = xxh64_round(v3, get_unaligned_le64(p));
+ p += 8;
+ v4 = xxh64_round(v4, get_unaligned_le64(p));
+ p += 8;
+ } while (p <= limit);
+
+ state->v1 = v1;
+ state->v2 = v2;
+ state->v3 = v3;
+ state->v4 = v4;
+ }
+
+ if (p < b_end) {
+ memcpy(state->mem64, p, (size_t)(b_end-p));
+ state->memsize = (uint32_t)(b_end - p);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(xxh64_update);
+
+uint64_t xxh64_digest(const struct xxh64_state *state)
+{
+ const uint8_t *p = (const uint8_t *)state->mem64;
+ const uint8_t *const b_end = (const uint8_t *)state->mem64 +
+ state->memsize;
+ uint64_t h64;
+
+ if (state->total_len >= 32) {
+ const uint64_t v1 = state->v1;
+ const uint64_t v2 = state->v2;
+ const uint64_t v3 = state->v3;
+ const uint64_t v4 = state->v4;
+
+ h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
+ xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
+ h64 = xxh64_merge_round(h64, v1);
+ h64 = xxh64_merge_round(h64, v2);
+ h64 = xxh64_merge_round(h64, v3);
+ h64 = xxh64_merge_round(h64, v4);
+ } else {
+ h64 = state->v3 + PRIME64_5;
+ }
+
+ h64 += (uint64_t)state->total_len;
+
+ while (p + 8 <= b_end) {
+ const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
+
+ h64 ^= k1;
+ h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
+ p += 8;
+ }
+
+ if (p + 4 <= b_end) {
+ h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
+ h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+ p += 4;
+ }
+
+ while (p < b_end) {
+ h64 ^= (*p) * PRIME64_5;
+ h64 = xxh_rotl64(h64, 11) * PRIME64_1;
+ p++;
+ }
+
+ h64 ^= h64 >> 33;
+ h64 *= PRIME64_2;
+ h64 ^= h64 >> 29;
+ h64 *= PRIME64_3;
+ h64 ^= h64 >> 32;
+
+ return h64;
+}
+EXPORT_SYMBOL(xxh64_digest);
diff --git a/lib/zlib/Makefile b/lib/zlib/Makefile
new file mode 100644
index 00000000..4a3e985a
--- /dev/null
+++ b/lib/zlib/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y += zlib.o
diff --git a/lib/zlib/adler32.c b/lib/zlib/adler32.c
new file mode 100644
index 00000000..b468441d
--- /dev/null
+++ b/lib/zlib/adler32.c
@@ -0,0 +1,122 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
new file mode 100644
index 00000000..1fe58d5d
--- /dev/null
+++ b/lib/zlib/deflate.c
@@ -0,0 +1,1833 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+#include <u-boot/crc.h>
+
+const char deflate_copyright[] =
+ " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle OF((deflate_state *s, int flush));
+local block_state deflate_huff OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->high_water = 0; /* nothing written to s->window yet */
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->wrap == 2 ||
+ (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+ return Z_STREAM_ERROR;
+
+ s = strm->state;
+ if (s->wrap)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > s->w_size) {
+ length = s->w_size;
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+ z_streamp strm;
+ int bits;
+ int value;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ strm->state->bi_valid = bits;
+ strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_BLOCK);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel. But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+ z_streamp strm;
+ uLong sourceLen;
+{
+ deflate_state *s;
+ uLong complen, wraplen;
+ Bytef *str;
+
+ /* conservative upper bound for compressed data */
+ complen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+
+ /* if can't get parameters, return conservative bound plus zlib wrapper */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return complen + 6;
+
+ /* compute wrapper length */
+ s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return conservative bound */
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return complen + wraplen;
+
+ /* default settings: return tight bound for that case */
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (s->status == FINISH_STATE && flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush));
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy(dest, source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, strm->next_in, len);
+ }
+#endif
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (last)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+ scan = s->window + s->strstart - 1;
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (int)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/lib/zlib/deflate.h b/lib/zlib/deflate.h
new file mode 100644
index 00000000..cbf0d1ea
--- /dev/null
+++ b/lib/zlib/deflate.h
@@ -0,0 +1,342 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
+ /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch ZLIB_INTERNAL _length_code[];
+ extern uch ZLIB_INTERNAL _dist_code[];
+#else
+ extern const uch ZLIB_INTERNAL _length_code[];
+ extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
new file mode 100644
index 00000000..e3c7f3b8
--- /dev/null
+++ b/lib/zlib/inffast.c
@@ -0,0 +1,356 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* U-Boot: we already included these
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+*/
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(z_streamp strm, unsigned start)
+/* start: inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code this; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ if (in > last && strm->avail_in > 5) {
+ /*
+ * overflow detected, limit strm->avail_in to the
+ * max. possible size and recalculate last
+ */
+ strm->avail_in = 0xffffffff - (uintptr_t)in;
+ last = in + (strm->avail_in - 5);
+ }
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ PUP(out) = (unsigned char)(this.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ unsigned short *sout;
+ unsigned long loops;
+
+ from = out - dist; /* copy direct from output */
+ /* minimum length is three */
+ /* Align out addr */
+ if (!((long)(out - 1 + OFF) & 1)) {
+ PUP(out) = PUP(from);
+ len--;
+ }
+ sout = (unsigned short *)(out - OFF);
+ if (dist > 2 ) {
+ unsigned short *sfrom;
+
+ sfrom = (unsigned short *)(from - OFF);
+ loops = len >> 1;
+ do
+ PUP(sout) = get_unaligned(++sfrom);
+ while (--loops);
+ out = (unsigned char *)sout + OFF;
+ from = (unsigned char *)sfrom + OFF;
+ } else { /* dist == 1 or dist == 2 */
+ unsigned short pat16;
+
+ pat16 = *(sout-2+2*OFF);
+ if (dist == 1)
+#if defined(__BIG_ENDIAN)
+ pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8);
+#elif defined(__LITTLE_ENDIAN)
+ pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8);
+#else
+#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
+#endif
+ loops = len >> 1;
+ do
+ PUP(sout) = pat16;
+ while (--loops);
+ out = (unsigned char *)sout + OFF;
+ }
+ if (len & 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ this = dcode[this.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ this = lcode[this.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/lib/zlib/inffast.h b/lib/zlib/inffast.h
new file mode 100644
index 00000000..1e88d2d9
--- /dev/null
+++ b/lib/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/lib/zlib/inffixed.h b/lib/zlib/inffixed.h
new file mode 100644
index 00000000..75ed4b59
--- /dev/null
+++ b/lib/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications. It
+ is part of the implementation of the compression library and
+ is subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c
new file mode 100644
index 00000000..6411c479
--- /dev/null
+++ b/lib/zlib/inflate.c
@@ -0,0 +1,943 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+
+int ZEXPORT inflateReset(z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ WATCHDOG_RESET();
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version,
+ int stream_size)
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size)
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+local void fixedtables(struct inflate_state FAR *state)
+{
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(z_streamp strm, unsigned out)
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+int ZEXPORT inflate(z_streamp strm, int flush)
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ WATCHDOG_RESET();
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ WATCHDOG_RESET();
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+ if ((int)(this.op) == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ state->mode = LIT;
+ break;
+ }
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(z_streamp strm)
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) {
+ WATCHDOG_RESET();
+ ZFREE(strm, state->window);
+ }
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/lib/zlib/inflate.h b/lib/zlib/inflate.h
new file mode 100644
index 00000000..07bd3e78
--- /dev/null
+++ b/lib/zlib/inflate.h
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
diff --git a/lib/zlib/inftrees.c b/lib/zlib/inftrees.c
new file mode 100644
index 00000000..b71b9695
--- /dev/null
+++ b/lib/zlib/inftrees.c
@@ -0,0 +1,325 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* U-Boot: we already included these
+#include "zutil.h"
+#include "inftrees.h"
+*/
+
+#define MAXBITS 15
+
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
+ code FAR * FAR *table, unsigned FAR *bits,
+ unsigned short FAR *work)
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code this; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)1;
+ this.val = (unsigned short)0;
+ *(*table)++ = this; /* make a table to force an error */
+ *(*table)++ = this;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ this.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ this.op = (unsigned char)0;
+ this.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ this.op = (unsigned char)(extra[work[sym]]);
+ this.val = base[work[sym]];
+ }
+ else {
+ this.op = (unsigned char)(32 + 64); /* end of block */
+ this.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = this;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)(len - drop);
+ this.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ this.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = this;
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/lib/zlib/inftrees.h b/lib/zlib/inftrees.h
new file mode 100644
index 00000000..b1104c87
--- /dev/null
+++ b/lib/zlib/inftrees.h
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/lib/zlib/trees.c b/lib/zlib/trees.c
new file mode 100644
index 00000000..a0078d08
--- /dev/null
+++ b/lib/zlib/trees.c
@@ -0,0 +1,1244 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local int detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (ush)val << s->bi_valid;\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header,
+ "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void ZLIB_INTERNAL _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+last, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+last, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "black list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(s)
+ deflate_state *s;
+{
+ /* black_mask is the bit mask of black-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long black_mask = 0xf3ffc07fUL;
+ int n;
+
+ /* Check for non-textual ("black-listed") bytes. */
+ for (n = 0; n <= 31; n++, black_mask >>= 1)
+ if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("white-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ return Z_TEXT;
+
+ /* There are no "black-listed" or "white-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(value, len)
+ unsigned value; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= value & 1;
+ value >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/lib/zlib/trees.h b/lib/zlib/trees.h
new file mode 100644
index 00000000..45a749f0
--- /dev/null
+++ b/lib/zlib/trees.h
@@ -0,0 +1,127 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
diff --git a/lib/zlib/zlib.c b/lib/zlib/zlib.c
new file mode 100644
index 00000000..7e157029
--- /dev/null
+++ b/lib/zlib/zlib.c
@@ -0,0 +1,32 @@
+/*
+ * This file is derived from various .h and .c files from the zlib-1.2.3
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets. See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_GZIP_COMPRESSED
+#define NO_DUMMY_DECL
+#include "deflate.c"
+#include "trees.c"
+#endif
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "inffixed.h"
+#include "inffast.c"
+#include "inftrees.c"
+#include "inflate.c"
+#include "zutil.c"
+#include "adler32.c"
diff --git a/lib/zlib/zlib.h b/lib/zlib/zlib.h
new file mode 100644
index 00000000..af3703e6
--- /dev/null
+++ b/lib/zlib/zlib.h
@@ -0,0 +1,20 @@
+/* Glue between u-boot and upstream zlib */
+#ifndef __GLUE_ZLIB_H__
+#define __GLUE_ZLIB_H__
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/unaligned.h>
+#include <watchdog.h>
+#include "u-boot/zlib.h"
+
+/* avoid conflicts */
+#undef OFF
+#undef ASMINF
+#undef POSTINC
+#undef NO_GZIP
+#define GUNZIP
+#undef STDC
+#undef NO_ERRNO_H
+
+#endif
diff --git a/lib/zlib/zutil.c b/lib/zlib/zutil.c
new file mode 100644
index 00000000..227343e4
--- /dev/null
+++ b/lib/zlib/zutil.c
@@ -0,0 +1,71 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+#ifdef DEBUG
+
+#ifndef verbose
+#define verbose 0
+#endif
+int z_verbose = verbose;
+
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ hang ();
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifdef __UBOOT__
+#include <malloc.h>
+#else
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+#endif
+
+voidpf zcalloc(voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque)
+ items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree(voidpf opaque, voidpf ptr, unsigned nb)
+{
+ free(ptr);
+ if (opaque)
+ return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/lib/zlib/zutil.h b/lib/zlib/zutil.h
new file mode 100644
index 00000000..e63bf686
--- /dev/null
+++ b/lib/zlib/zutil.h
@@ -0,0 +1,126 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
+ extern int errno;
+#else
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+ /* functions */
+#ifdef CONFIG_GZIP_COMPRESSED
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#include <linux/string.h>
+#define zmemcpy memcpy
+#define zmemcmp memcmp
+#define zmemzero(dest, len) memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef DEBUG
+/* Not valid for U-Boot
+# include <stdio.h> */
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr, unsigned size));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), 0)
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/lib/zstd/Makefile b/lib/zstd/Makefile
new file mode 100644
index 00000000..33c1df48
--- /dev/null
+++ b/lib/zstd/Makefile
@@ -0,0 +1,4 @@
+obj-y += zstd_decompress.o
+
+zstd_decompress-y := huf_decompress.o decompress.o \
+ entropy_common.o fse_decompress.o zstd_common.o
diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h
new file mode 100644
index 00000000..73aacc97
--- /dev/null
+++ b/lib/zstd/bitstream.h
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
+/*
+ * bitstream
+ * Part of FSE library
+ * header file (to include)
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef BITSTREAM_H_MODULE
+#define BITSTREAM_H_MODULE
+
+/*
+* This API consists of small unitary functions, which must be inlined for best performance.
+* Since link-time-optimization is not available for all compilers,
+* these functions are defined into a .h to be included.
+*/
+
+/*-****************************************
+* Dependencies
+******************************************/
+#include "error_private.h" /* error codes and messages */
+#include "mem.h" /* unaligned access routines */
+
+/*=========================================
+* Target specific
+=========================================*/
+#define STREAM_ACCUMULATOR_MIN_32 25
+#define STREAM_ACCUMULATOR_MIN_64 57
+#define STREAM_ACCUMULATOR_MIN ((U32)(ZSTD_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
+
+/*-******************************************
+* bitStream encoding API (write forward)
+********************************************/
+/* bitStream can mix input from multiple sources.
+* A critical property of these streams is that they encode and decode in **reverse** direction.
+* So the first bit sequence you add will be the last to be read, like a LIFO stack.
+*/
+typedef struct {
+ size_t bitContainer;
+ int bitPos;
+ char *startPtr;
+ char *ptr;
+ char *endPtr;
+} BIT_CStream_t;
+
+ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *dstBuffer, size_t dstCapacity);
+ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
+ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC);
+ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC);
+
+/* Start with initCStream, providing the size of buffer to write into.
+* bitStream will never write outside of this buffer.
+* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
+*
+* bits are first added to a local register.
+* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
+* Writing data into memory is an explicit operation, performed by the flushBits function.
+* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
+* After a flushBits, a maximum of 7 bits might still be stored into local register.
+*
+* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
+*
+* Last operation is to close the bitStream.
+* The function returns the final size of CStream in bytes.
+* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
+*/
+
+/*-********************************************
+* bitStream decoding API (read backward)
+**********************************************/
+typedef struct {
+ size_t bitContainer;
+ unsigned bitsConsumed;
+ const char *ptr;
+ const char *start;
+} BIT_DStream_t;
+
+typedef enum {
+ BIT_DStream_unfinished = 0,
+ BIT_DStream_endOfBuffer = 1,
+ BIT_DStream_completed = 2,
+ BIT_DStream_overflow = 3
+} BIT_DStream_status; /* result of BIT_reloadDStream() */
+/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
+
+ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize);
+ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, unsigned nbBits);
+ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD);
+ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *bitD);
+
+/* Start by invoking BIT_initDStream().
+* A chunk of the bitStream is then stored into a local register.
+* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+* You can then retrieve bitFields stored into the local register, **in reverse order**.
+* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
+* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
+* Otherwise, it can be less than that, so proceed accordingly.
+* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
+*/
+
+/*-****************************************
+* unsafe API
+******************************************/
+ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
+/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
+
+ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC);
+/* unsafe version; does not check buffer overflow */
+
+ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits);
+/* faster, but works only if nbBits >= 1 */
+
+/*-**************************************************************
+* Internal functions
+****************************************************************/
+ZSTD_STATIC unsigned BIT_highbit32(register U32 val) { return 31 - __builtin_clz(val); }
+
+/*===== Local Constants =====*/
+static const unsigned BIT_mask[] = {0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
+ 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
+ 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF}; /* up to 26 bits */
+
+/*-**************************************************************
+* bitStream encoding
+****************************************************************/
+/*! BIT_initCStream() :
+ * `dstCapacity` must be > sizeof(void*)
+ * @return : 0 if success,
+ otherwise an error code (can be tested using ERR_isError() ) */
+ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *startPtr, size_t dstCapacity)
+{
+ bitC->bitContainer = 0;
+ bitC->bitPos = 0;
+ bitC->startPtr = (char *)startPtr;
+ bitC->ptr = bitC->startPtr;
+ bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
+ if (dstCapacity <= sizeof(bitC->ptr))
+ return ERROR(dstSize_tooSmall);
+ return 0;
+}
+
+/*! BIT_addBits() :
+ can add up to 26 bits into `bitC`.
+ Does not check for register overflow ! */
+ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
+{
+ bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
+ bitC->bitPos += nbBits;
+}
+
+/*! BIT_addBitsFast() :
+ * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
+ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
+{
+ bitC->bitContainer |= value << bitC->bitPos;
+ bitC->bitPos += nbBits;
+}
+
+/*! BIT_flushBitsFast() :
+ * unsafe version; does not check buffer overflow */
+ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC)
+{
+ size_t const nbBytes = bitC->bitPos >> 3;
+ ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
+ bitC->ptr += nbBytes;
+ bitC->bitPos &= 7;
+ bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
+}
+
+/*! BIT_flushBits() :
+ * safe version; check for buffer overflow, and prevents it.
+ * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
+ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC)
+{
+ size_t const nbBytes = bitC->bitPos >> 3;
+ ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
+ bitC->ptr += nbBytes;
+ if (bitC->ptr > bitC->endPtr)
+ bitC->ptr = bitC->endPtr;
+ bitC->bitPos &= 7;
+ bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
+}
+
+/*! BIT_closeCStream() :
+ * @return : size of CStream, in bytes,
+ or 0 if it could not fit into dstBuffer */
+ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC)
+{
+ BIT_addBitsFast(bitC, 1, 1); /* endMark */
+ BIT_flushBits(bitC);
+
+ if (bitC->ptr >= bitC->endPtr)
+ return 0; /* doesn't fit within authorized budget : cancel */
+
+ return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
+}
+
+/*-********************************************************
+* bitStream decoding
+**********************************************************/
+/*! BIT_initDStream() :
+* Initialize a BIT_DStream_t.
+* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
+* `srcSize` must be the *exact* size of the bitStream, in bytes.
+* @return : size of stream (== srcSize) or an errorCode if a problem is detected
+*/
+ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize)
+{
+ if (srcSize < 1) {
+ memset(bitD, 0, sizeof(*bitD));
+ return ERROR(srcSize_wrong);
+ }
+
+ if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
+ bitD->start = (const char *)srcBuffer;
+ bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(bitD->bitContainer);
+ bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
+ {
+ BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
+ bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
+ if (lastByte == 0)
+ return ERROR(GENERIC); /* endMark not present */
+ }
+ } else {
+ bitD->start = (const char *)srcBuffer;
+ bitD->ptr = bitD->start;
+ bitD->bitContainer = *(const BYTE *)(bitD->start);
+ switch (srcSize) {
+ case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16);
+ case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24);
+ case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32);
+ case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24;
+ case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16;
+ case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8;
+ default:;
+ }
+ {
+ BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
+ bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
+ if (lastByte == 0)
+ return ERROR(GENERIC); /* endMark not present */
+ }
+ bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize) * 8;
+ }
+
+ return srcSize;
+}
+
+ZSTD_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; }
+
+ZSTD_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { return (bitContainer >> start) & BIT_mask[nbBits]; }
+
+ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { return bitContainer & BIT_mask[nbBits]; }
+
+/*! BIT_lookBits() :
+ * Provides next n bits from local register.
+ * local register is not modified.
+ * On 32-bits, maxNbBits==24.
+ * On 64-bits, maxNbBits==56.
+ * @return : value extracted
+ */
+ZSTD_STATIC size_t BIT_lookBits(const BIT_DStream_t *bitD, U32 nbBits)
+{
+ U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
+ return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask);
+}
+
+/*! BIT_lookBitsFast() :
+* unsafe version; only works only if nbBits >= 1 */
+ZSTD_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t *bitD, U32 nbBits)
+{
+ U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
+ return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask);
+}
+
+ZSTD_STATIC void BIT_skipBits(BIT_DStream_t *bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; }
+
+/*! BIT_readBits() :
+ * Read (consume) next n bits from local register and update.
+ * Pay attention to not read more than nbBits contained into local register.
+ * @return : extracted value.
+ */
+ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, U32 nbBits)
+{
+ size_t const value = BIT_lookBits(bitD, nbBits);
+ BIT_skipBits(bitD, nbBits);
+ return value;
+}
+
+/*! BIT_readBitsFast() :
+* unsafe version; only works only if nbBits >= 1 */
+ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, U32 nbBits)
+{
+ size_t const value = BIT_lookBitsFast(bitD, nbBits);
+ BIT_skipBits(bitD, nbBits);
+ return value;
+}
+
+/*! BIT_reloadDStream() :
+* Refill `bitD` from buffer previously set in BIT_initDStream() .
+* This function is safe, it guarantees it will not read beyond src buffer.
+* @return : status of `BIT_DStream_t` internal register.
+ if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
+ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD)
+{
+ if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should not happen => corruption detected */
+ return BIT_DStream_overflow;
+
+ if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
+ bitD->ptr -= bitD->bitsConsumed >> 3;
+ bitD->bitsConsumed &= 7;
+ bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
+ return BIT_DStream_unfinished;
+ }
+ if (bitD->ptr == bitD->start) {
+ if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8)
+ return BIT_DStream_endOfBuffer;
+ return BIT_DStream_completed;
+ }
+ {
+ U32 nbBytes = bitD->bitsConsumed >> 3;
+ BIT_DStream_status result = BIT_DStream_unfinished;
+ if (bitD->ptr - nbBytes < bitD->start) {
+ nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
+ result = BIT_DStream_endOfBuffer;
+ }
+ bitD->ptr -= nbBytes;
+ bitD->bitsConsumed -= nbBytes * 8;
+ bitD->bitContainer = ZSTD_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
+ return result;
+ }
+}
+
+/*! BIT_endOfDStream() :
+* @return Tells if DStream has exactly reached its end (all bits consumed).
+*/
+ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *DStream)
+{
+ return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer) * 8));
+}
+
+#endif /* BITSTREAM_H_MODULE */
diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c
new file mode 100644
index 00000000..ac5ab528
--- /dev/null
+++ b/lib/zstd/decompress.c
@@ -0,0 +1,2515 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear)
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+/* ***************************************************************
+* Tuning parameters
+*****************************************************************/
+/*!
+* MAXWINDOWSIZE_DEFAULT :
+* maximum window size accepted by DStream, by default.
+* Frames requiring more memory will be rejected.
+*/
+#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
+#define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
+#endif
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include "fse.h"
+#include "huf.h"
+#include "mem.h" /* low level memory routines */
+#include "zstd_internal.h"
+#include <linux/kernel.h>
+#include <linux/compat.h>
+#include <linux/string.h> /* memcpy, memmove, memset */
+
+#define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
+
+/*-*************************************
+* Macros
+***************************************/
+#define ZSTD_isError ERR_isError /* for inlining */
+#define FSE_isError ERR_isError
+#define HUF_isError ERR_isError
+
+/*_*******************************************************
+* Memory operations
+**********************************************************/
+static void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); }
+
+/*-*************************************************************
+* Context management
+***************************************************************/
+typedef enum {
+ ZSTDds_getFrameHeaderSize,
+ ZSTDds_decodeFrameHeader,
+ ZSTDds_decodeBlockHeader,
+ ZSTDds_decompressBlock,
+ ZSTDds_decompressLastBlock,
+ ZSTDds_checkChecksum,
+ ZSTDds_decodeSkippableHeader,
+ ZSTDds_skipFrame
+} ZSTD_dStage;
+
+typedef struct {
+ FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
+ FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
+ FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
+ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
+ U64 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32 / 2];
+ U32 rep[ZSTD_REP_NUM];
+} ZSTD_entropyTables_t;
+
+struct ZSTD_DCtx_s {
+ const FSE_DTable *LLTptr;
+ const FSE_DTable *MLTptr;
+ const FSE_DTable *OFTptr;
+ const HUF_DTable *HUFptr;
+ ZSTD_entropyTables_t entropy;
+ const void *previousDstEnd; /* detect continuity */
+ const void *base; /* start of curr segment */
+ const void *vBase; /* virtual start of previous segment if it was just before curr one */
+ const void *dictEnd; /* end of previous segment */
+ size_t expected;
+ ZSTD_frameParams fParams;
+ blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
+ ZSTD_dStage stage;
+ U32 litEntropy;
+ U32 fseEntropy;
+ struct xxh64_state xxhState;
+ size_t headerSize;
+ U32 dictID;
+ const BYTE *litPtr;
+ ZSTD_customMem customMem;
+ size_t litSize;
+ size_t rleSize;
+ BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
+}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
+
+size_t ZSTD_DCtxWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DCtx)); }
+
+size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx)
+{
+ dctx->expected = ZSTD_frameHeaderSize_prefix;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ dctx->previousDstEnd = NULL;
+ dctx->base = NULL;
+ dctx->vBase = NULL;
+ dctx->dictEnd = NULL;
+ dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+ dctx->litEntropy = dctx->fseEntropy = 0;
+ dctx->dictID = 0;
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
+ memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+ dctx->LLTptr = dctx->entropy.LLTable;
+ dctx->MLTptr = dctx->entropy.MLTable;
+ dctx->OFTptr = dctx->entropy.OFTable;
+ dctx->HUFptr = dctx->entropy.hufTable;
+ return 0;
+}
+
+ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
+{
+ ZSTD_DCtx *dctx;
+
+ if (!customMem.customAlloc || !customMem.customFree)
+ return NULL;
+
+ dctx = (ZSTD_DCtx *)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
+ if (!dctx)
+ return NULL;
+ memcpy(&dctx->customMem, &customMem, sizeof(customMem));
+ ZSTD_decompressBegin(dctx);
+ return dctx;
+}
+
+ZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize)
+{
+ ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+ return ZSTD_createDCtx_advanced(stackMem);
+}
+
+size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx)
+{
+ if (dctx == NULL)
+ return 0; /* support free on NULL */
+ ZSTD_free(dctx, dctx->customMem);
+ return 0; /* reserved as a potential error code in the future */
+}
+
+void ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx)
+{
+ size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max;
+ memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
+}
+
+static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict);
+
+/*-*************************************************************
+* Decompression section
+***************************************************************/
+
+/*! ZSTD_isFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier.
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
+ * Note 3 : Skippable Frame Identifiers are considered valid. */
+unsigned ZSTD_isFrame(const void *buffer, size_t size)
+{
+ if (size < 4)
+ return 0;
+ {
+ U32 const magic = ZSTD_readLE32(buffer);
+ if (magic == ZSTD_MAGICNUMBER)
+ return 1;
+ if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START)
+ return 1;
+ }
+ return 0;
+}
+
+/** ZSTD_frameHeaderSize() :
+* srcSize must be >= ZSTD_frameHeaderSize_prefix.
+* @return : size of the Frame Header */
+static size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize)
+{
+ if (srcSize < ZSTD_frameHeaderSize_prefix)
+ return ERROR(srcSize_wrong);
+ {
+ BYTE const fhd = ((const BYTE *)src)[4];
+ U32 const dictID = fhd & 3;
+ U32 const singleSegment = (fhd >> 5) & 1;
+ U32 const fcsId = fhd >> 6;
+ return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + (singleSegment && !fcsId);
+ }
+}
+
+/** ZSTD_getFrameParams() :
+* decode Frame Header, or require larger `srcSize`.
+* @return : 0, `fparamsPtr` is correctly filled,
+* >0, `srcSize` is too small, result is expected `srcSize`,
+* or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize)
+{
+ const BYTE *ip = (const BYTE *)src;
+
+ if (srcSize < ZSTD_frameHeaderSize_prefix)
+ return ZSTD_frameHeaderSize_prefix;
+ if (ZSTD_readLE32(src) != ZSTD_MAGICNUMBER) {
+ if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+ if (srcSize < ZSTD_skippableHeaderSize)
+ return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
+ memset(fparamsPtr, 0, sizeof(*fparamsPtr));
+ fparamsPtr->frameContentSize = ZSTD_readLE32((const char *)src + 4);
+ fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
+ return 0;
+ }
+ return ERROR(prefix_unknown);
+ }
+
+ /* ensure there is enough `srcSize` to fully read/decode frame header */
+ {
+ size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
+ if (srcSize < fhsize)
+ return fhsize;
+ }
+
+ {
+ BYTE const fhdByte = ip[4];
+ size_t pos = 5;
+ U32 const dictIDSizeCode = fhdByte & 3;
+ U32 const checksumFlag = (fhdByte >> 2) & 1;
+ U32 const singleSegment = (fhdByte >> 5) & 1;
+ U32 const fcsID = fhdByte >> 6;
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;
+ U32 windowSize = 0;
+ U32 dictID = 0;
+ U64 frameContentSize = 0;
+ if ((fhdByte & 0x08) != 0)
+ return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */
+ if (!singleSegment) {
+ BYTE const wlByte = ip[pos++];
+ U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
+ if (windowLog > ZSTD_WINDOWLOG_MAX)
+ return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */
+ windowSize = (1U << windowLog);
+ windowSize += (windowSize >> 3) * (wlByte & 7);
+ }
+
+ switch (dictIDSizeCode) {
+ default: /* impossible */
+ case 0: break;
+ case 1:
+ dictID = ip[pos];
+ pos++;
+ break;
+ case 2:
+ dictID = ZSTD_readLE16(ip + pos);
+ pos += 2;
+ break;
+ case 3:
+ dictID = ZSTD_readLE32(ip + pos);
+ pos += 4;
+ break;
+ }
+ switch (fcsID) {
+ default: /* impossible */
+ case 0:
+ if (singleSegment)
+ frameContentSize = ip[pos];
+ break;
+ case 1: frameContentSize = ZSTD_readLE16(ip + pos) + 256; break;
+ case 2: frameContentSize = ZSTD_readLE32(ip + pos); break;
+ case 3: frameContentSize = ZSTD_readLE64(ip + pos); break;
+ }
+ if (!windowSize)
+ windowSize = (U32)frameContentSize;
+ if (windowSize > windowSizeMax)
+ return ERROR(frameParameter_windowTooLarge);
+ fparamsPtr->frameContentSize = frameContentSize;
+ fparamsPtr->windowSize = windowSize;
+ fparamsPtr->dictID = dictID;
+ fparamsPtr->checksumFlag = checksumFlag;
+ }
+ return 0;
+}
+
+/** ZSTD_getFrameContentSize() :
+* compatible with legacy mode
+* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
+* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
+* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
+unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
+{
+ {
+ ZSTD_frameParams fParams;
+ if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0)
+ return ZSTD_CONTENTSIZE_ERROR;
+ if (fParams.windowSize == 0) {
+ /* Either skippable or empty frame, size == 0 either way */
+ return 0;
+ } else if (fParams.frameContentSize != 0) {
+ return fParams.frameContentSize;
+ } else {
+ return ZSTD_CONTENTSIZE_UNKNOWN;
+ }
+ }
+}
+
+/** ZSTD_findDecompressedSize() :
+ * compatible with legacy mode
+ * `srcSize` must be the exact length of some number of ZSTD compressed and/or
+ * skippable frames
+ * @return : decompressed size of the frames contained */
+unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize)
+{
+ {
+ unsigned long long totalDstSize = 0;
+ while (srcSize >= ZSTD_frameHeaderSize_prefix) {
+ const U32 magicNumber = ZSTD_readLE32(src);
+
+ if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t skippableSize;
+ if (srcSize < ZSTD_skippableHeaderSize)
+ return ERROR(srcSize_wrong);
+ skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
+ if (srcSize < skippableSize) {
+ return ZSTD_CONTENTSIZE_ERROR;
+ }
+
+ src = (const BYTE *)src + skippableSize;
+ srcSize -= skippableSize;
+ continue;
+ }
+
+ {
+ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
+ if (ret >= ZSTD_CONTENTSIZE_ERROR)
+ return ret;
+
+ /* check for overflow */
+ if (totalDstSize + ret < totalDstSize)
+ return ZSTD_CONTENTSIZE_ERROR;
+ totalDstSize += ret;
+ }
+ {
+ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
+ if (ZSTD_isError(frameSrcSize)) {
+ return ZSTD_CONTENTSIZE_ERROR;
+ }
+
+ src = (const BYTE *)src + frameSrcSize;
+ srcSize -= frameSrcSize;
+ }
+ }
+
+ if (srcSize) {
+ return ZSTD_CONTENTSIZE_ERROR;
+ }
+
+ return totalDstSize;
+ }
+}
+
+/** ZSTD_decodeFrameHeader() :
+* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
+* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
+static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize)
+{
+ size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize);
+ if (ZSTD_isError(result))
+ return result; /* invalid header */
+ if (result > 0)
+ return ERROR(srcSize_wrong); /* headerSize too small */
+ if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
+ return ERROR(dictionary_wrong);
+ if (dctx->fParams.checksumFlag)
+ xxh64_reset(&dctx->xxhState, 0);
+ return 0;
+}
+
+typedef struct {
+ blockType_e blockType;
+ U32 lastBlock;
+ U32 origSize;
+} blockProperties_t;
+
+/*! ZSTD_getcBlockSize() :
+* Provides the size of compressed block from block header `src` */
+size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr)
+{
+ if (srcSize < ZSTD_blockHeaderSize)
+ return ERROR(srcSize_wrong);
+ {
+ U32 const cBlockHeader = ZSTD_readLE24(src);
+ U32 const cSize = cBlockHeader >> 3;
+ bpPtr->lastBlock = cBlockHeader & 1;
+ bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
+ bpPtr->origSize = cSize; /* only useful for RLE */
+ if (bpPtr->blockType == bt_rle)
+ return 1;
+ if (bpPtr->blockType == bt_reserved)
+ return ERROR(corruption_detected);
+ return cSize;
+ }
+}
+
+static size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+ if (srcSize > dstCapacity)
+ return ERROR(dstSize_tooSmall);
+ memcpy(dst, src, srcSize);
+ return srcSize;
+}
+
+static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize, size_t regenSize)
+{
+ if (srcSize != 1)
+ return ERROR(srcSize_wrong);
+ if (regenSize > dstCapacity)
+ return ERROR(dstSize_tooSmall);
+ memset(dst, *(const BYTE *)src, regenSize);
+ return regenSize;
+}
+
+/*! ZSTD_decodeLiteralsBlock() :
+ @return : nb of bytes read from src (< srcSize ) */
+size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
+{
+ if (srcSize < MIN_CBLOCK_SIZE)
+ return ERROR(corruption_detected);
+
+ {
+ const BYTE *const istart = (const BYTE *)src;
+ symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
+
+ switch (litEncType) {
+ case set_repeat:
+ if (dctx->litEntropy == 0)
+ return ERROR(dictionary_corrupted);
+ /* fall-through */
+ case set_compressed:
+ if (srcSize < 5)
+ return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
+ {
+ size_t lhSize, litSize, litCSize;
+ U32 singleStream = 0;
+ U32 const lhlCode = (istart[0] >> 2) & 3;
+ U32 const lhc = ZSTD_readLE32(istart);
+ switch (lhlCode) {
+ case 0:
+ case 1:
+ default: /* note : default is impossible, since lhlCode into [0..3] */
+ /* 2 - 2 - 10 - 10 */
+ singleStream = !lhlCode;
+ lhSize = 3;
+ litSize = (lhc >> 4) & 0x3FF;
+ litCSize = (lhc >> 14) & 0x3FF;
+ break;
+ case 2:
+ /* 2 - 2 - 14 - 14 */
+ lhSize = 4;
+ litSize = (lhc >> 4) & 0x3FFF;
+ litCSize = lhc >> 18;
+ break;
+ case 3:
+ /* 2 - 2 - 18 - 18 */
+ lhSize = 5;
+ litSize = (lhc >> 4) & 0x3FFFF;
+ litCSize = (lhc >> 22) + (istart[4] << 10);
+ break;
+ }
+ if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+ return ERROR(corruption_detected);
+ if (litCSize + lhSize > srcSize)
+ return ERROR(corruption_detected);
+
+ if (HUF_isError(
+ (litEncType == set_repeat)
+ ? (singleStream ? HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr)
+ : HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr))
+ : (singleStream
+ ? HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace))
+ : HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
+ return ERROR(corruption_detected);
+
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ dctx->litEntropy = 1;
+ if (litEncType == set_compressed)
+ dctx->HUFptr = dctx->entropy.hufTable;
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ return litCSize + lhSize;
+ }
+
+ case set_basic: {
+ size_t litSize, lhSize;
+ U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ switch (lhlCode) {
+ case 0:
+ case 2:
+ default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = ZSTD_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = ZSTD_readLE24(istart) >> 4;
+ break;
+ }
+
+ if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
+ if (litSize + lhSize > srcSize)
+ return ERROR(corruption_detected);
+ memcpy(dctx->litBuffer, istart + lhSize, litSize);
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ return lhSize + litSize;
+ }
+ /* direct reference into compressed stream */
+ dctx->litPtr = istart + lhSize;
+ dctx->litSize = litSize;
+ return lhSize + litSize;
+ }
+
+ case set_rle: {
+ U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ size_t litSize, lhSize;
+ switch (lhlCode) {
+ case 0:
+ case 2:
+ default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = ZSTD_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = ZSTD_readLE24(istart) >> 4;
+ if (srcSize < 4)
+ return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
+ break;
+ }
+ if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+ return ERROR(corruption_detected);
+ memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ return lhSize + 1;
+ }
+ default:
+ return ERROR(corruption_detected); /* impossible */
+ }
+ }
+}
+
+typedef union {
+ FSE_decode_t realData;
+ U32 alignedBy4;
+} FSE_decode_t4;
+
+static const FSE_decode_t4 LL_defaultDTable[(1 << LL_DEFAULTNORMLOG) + 1] = {
+ {{LL_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+ {{0, 0, 4}}, /* 0 : base, symbol, bits */
+ {{16, 0, 4}},
+ {{32, 1, 5}},
+ {{0, 3, 5}},
+ {{0, 4, 5}},
+ {{0, 6, 5}},
+ {{0, 7, 5}},
+ {{0, 9, 5}},
+ {{0, 10, 5}},
+ {{0, 12, 5}},
+ {{0, 14, 6}},
+ {{0, 16, 5}},
+ {{0, 18, 5}},
+ {{0, 19, 5}},
+ {{0, 21, 5}},
+ {{0, 22, 5}},
+ {{0, 24, 5}},
+ {{32, 25, 5}},
+ {{0, 26, 5}},
+ {{0, 27, 6}},
+ {{0, 29, 6}},
+ {{0, 31, 6}},
+ {{32, 0, 4}},
+ {{0, 1, 4}},
+ {{0, 2, 5}},
+ {{32, 4, 5}},
+ {{0, 5, 5}},
+ {{32, 7, 5}},
+ {{0, 8, 5}},
+ {{32, 10, 5}},
+ {{0, 11, 5}},
+ {{0, 13, 6}},
+ {{32, 16, 5}},
+ {{0, 17, 5}},
+ {{32, 19, 5}},
+ {{0, 20, 5}},
+ {{32, 22, 5}},
+ {{0, 23, 5}},
+ {{0, 25, 4}},
+ {{16, 25, 4}},
+ {{32, 26, 5}},
+ {{0, 28, 6}},
+ {{0, 30, 6}},
+ {{48, 0, 4}},
+ {{16, 1, 4}},
+ {{32, 2, 5}},
+ {{32, 3, 5}},
+ {{32, 5, 5}},
+ {{32, 6, 5}},
+ {{32, 8, 5}},
+ {{32, 9, 5}},
+ {{32, 11, 5}},
+ {{32, 12, 5}},
+ {{0, 15, 6}},
+ {{32, 17, 5}},
+ {{32, 18, 5}},
+ {{32, 20, 5}},
+ {{32, 21, 5}},
+ {{32, 23, 5}},
+ {{32, 24, 5}},
+ {{0, 35, 6}},
+ {{0, 34, 6}},
+ {{0, 33, 6}},
+ {{0, 32, 6}},
+}; /* LL_defaultDTable */
+
+static const FSE_decode_t4 ML_defaultDTable[(1 << ML_DEFAULTNORMLOG) + 1] = {
+ {{ML_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+ {{0, 0, 6}}, /* 0 : base, symbol, bits */
+ {{0, 1, 4}},
+ {{32, 2, 5}},
+ {{0, 3, 5}},
+ {{0, 5, 5}},
+ {{0, 6, 5}},
+ {{0, 8, 5}},
+ {{0, 10, 6}},
+ {{0, 13, 6}},
+ {{0, 16, 6}},
+ {{0, 19, 6}},
+ {{0, 22, 6}},
+ {{0, 25, 6}},
+ {{0, 28, 6}},
+ {{0, 31, 6}},
+ {{0, 33, 6}},
+ {{0, 35, 6}},
+ {{0, 37, 6}},
+ {{0, 39, 6}},
+ {{0, 41, 6}},
+ {{0, 43, 6}},
+ {{0, 45, 6}},
+ {{16, 1, 4}},
+ {{0, 2, 4}},
+ {{32, 3, 5}},
+ {{0, 4, 5}},
+ {{32, 6, 5}},
+ {{0, 7, 5}},
+ {{0, 9, 6}},
+ {{0, 12, 6}},
+ {{0, 15, 6}},
+ {{0, 18, 6}},
+ {{0, 21, 6}},
+ {{0, 24, 6}},
+ {{0, 27, 6}},
+ {{0, 30, 6}},
+ {{0, 32, 6}},
+ {{0, 34, 6}},
+ {{0, 36, 6}},
+ {{0, 38, 6}},
+ {{0, 40, 6}},
+ {{0, 42, 6}},
+ {{0, 44, 6}},
+ {{32, 1, 4}},
+ {{48, 1, 4}},
+ {{16, 2, 4}},
+ {{32, 4, 5}},
+ {{32, 5, 5}},
+ {{32, 7, 5}},
+ {{32, 8, 5}},
+ {{0, 11, 6}},
+ {{0, 14, 6}},
+ {{0, 17, 6}},
+ {{0, 20, 6}},
+ {{0, 23, 6}},
+ {{0, 26, 6}},
+ {{0, 29, 6}},
+ {{0, 52, 6}},
+ {{0, 51, 6}},
+ {{0, 50, 6}},
+ {{0, 49, 6}},
+ {{0, 48, 6}},
+ {{0, 47, 6}},
+ {{0, 46, 6}},
+}; /* ML_defaultDTable */
+
+static const FSE_decode_t4 OF_defaultDTable[(1 << OF_DEFAULTNORMLOG) + 1] = {
+ {{OF_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+ {{0, 0, 5}}, /* 0 : base, symbol, bits */
+ {{0, 6, 4}},
+ {{0, 9, 5}},
+ {{0, 15, 5}},
+ {{0, 21, 5}},
+ {{0, 3, 5}},
+ {{0, 7, 4}},
+ {{0, 12, 5}},
+ {{0, 18, 5}},
+ {{0, 23, 5}},
+ {{0, 5, 5}},
+ {{0, 8, 4}},
+ {{0, 14, 5}},
+ {{0, 20, 5}},
+ {{0, 2, 5}},
+ {{16, 7, 4}},
+ {{0, 11, 5}},
+ {{0, 17, 5}},
+ {{0, 22, 5}},
+ {{0, 4, 5}},
+ {{16, 8, 4}},
+ {{0, 13, 5}},
+ {{0, 19, 5}},
+ {{0, 1, 5}},
+ {{16, 6, 4}},
+ {{0, 10, 5}},
+ {{0, 16, 5}},
+ {{0, 28, 5}},
+ {{0, 27, 5}},
+ {{0, 26, 5}},
+ {{0, 25, 5}},
+ {{0, 24, 5}},
+}; /* OF_defaultDTable */
+
+/*! ZSTD_buildSeqTable() :
+ @return : nb bytes read from src,
+ or an error code if it fails, testable with ZSTD_isError()
+*/
+static size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTablePtr, symbolEncodingType_e type, U32 max, U32 maxLog, const void *src,
+ size_t srcSize, const FSE_decode_t4 *defaultTable, U32 flagRepeatTable, void *workspace, size_t workspaceSize)
+{
+ const void *const tmpPtr = defaultTable; /* bypass strict aliasing */
+ switch (type) {
+ case set_rle:
+ if (!srcSize)
+ return ERROR(srcSize_wrong);
+ if ((*(const BYTE *)src) > max)
+ return ERROR(corruption_detected);
+ FSE_buildDTable_rle(DTableSpace, *(const BYTE *)src);
+ *DTablePtr = DTableSpace;
+ return 1;
+ case set_basic: *DTablePtr = (const FSE_DTable *)tmpPtr; return 0;
+ case set_repeat:
+ if (!flagRepeatTable)
+ return ERROR(corruption_detected);
+ return 0;
+ default: /* impossible */
+ case set_compressed: {
+ U32 tableLog;
+ S16 *norm = (S16 *)workspace;
+ size_t const spaceUsed32 = ALIGN(sizeof(S16) * (MaxSeq + 1), sizeof(U32)) >> 2;
+
+ if ((spaceUsed32 << 2) > workspaceSize)
+ return ERROR(GENERIC);
+ workspace = (U32 *)workspace + spaceUsed32;
+ workspaceSize -= (spaceUsed32 << 2);
+ {
+ size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
+ if (FSE_isError(headerSize))
+ return ERROR(corruption_detected);
+ if (tableLog > maxLog)
+ return ERROR(corruption_detected);
+ FSE_buildDTable_wksp(DTableSpace, norm, max, tableLog, workspace, workspaceSize);
+ *DTablePtr = DTableSpace;
+ return headerSize;
+ }
+ }
+ }
+}
+
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize)
+{
+ const BYTE *const istart = (const BYTE *const)src;
+ const BYTE *const iend = istart + srcSize;
+ const BYTE *ip = istart;
+
+ /* check */
+ if (srcSize < MIN_SEQUENCES_SIZE)
+ return ERROR(srcSize_wrong);
+
+ /* SeqHead */
+ {
+ int nbSeq = *ip++;
+ if (!nbSeq) {
+ *nbSeqPtr = 0;
+ return 1;
+ }
+ if (nbSeq > 0x7F) {
+ if (nbSeq == 0xFF) {
+ if (ip + 2 > iend)
+ return ERROR(srcSize_wrong);
+ nbSeq = ZSTD_readLE16(ip) + LONGNBSEQ, ip += 2;
+ } else {
+ if (ip >= iend)
+ return ERROR(srcSize_wrong);
+ nbSeq = ((nbSeq - 0x80) << 8) + *ip++;
+ }
+ }
+ *nbSeqPtr = nbSeq;
+ }
+
+ /* FSE table descriptors */
+ if (ip + 4 > iend)
+ return ERROR(srcSize_wrong); /* minimum possible size */
+ {
+ symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
+ symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
+ symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
+ ip++;
+
+ /* Build DTables */
+ {
+ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, LLtype, MaxLL, LLFSELog, ip, iend - ip,
+ LL_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+ if (ZSTD_isError(llhSize))
+ return ERROR(corruption_detected);
+ ip += llhSize;
+ }
+ {
+ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, OFtype, MaxOff, OffFSELog, ip, iend - ip,
+ OF_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+ if (ZSTD_isError(ofhSize))
+ return ERROR(corruption_detected);
+ ip += ofhSize;
+ }
+ {
+ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, MLtype, MaxML, MLFSELog, ip, iend - ip,
+ ML_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+ if (ZSTD_isError(mlhSize))
+ return ERROR(corruption_detected);
+ ip += mlhSize;
+ }
+ }
+
+ return ip - istart;
+}
+
+typedef struct {
+ size_t litLength;
+ size_t matchLength;
+ size_t offset;
+ const BYTE *match;
+} seq_t;
+
+typedef struct {
+ BIT_DStream_t DStream;
+ FSE_DState_t stateLL;
+ FSE_DState_t stateOffb;
+ FSE_DState_t stateML;
+ size_t prevOffset[ZSTD_REP_NUM];
+ const BYTE *base;
+ size_t pos;
+ uPtrDiff gotoDict;
+} seqState_t;
+
+FORCE_NOINLINE
+size_t ZSTD_execSequenceLast7(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+ const BYTE *const vBase, const BYTE *const dictEnd)
+{
+ BYTE *const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE *match = oLitEnd - sequence.offset;
+
+ /* check */
+ if (oMatchEnd > oend)
+ return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+ if (iLitEnd > litLimit)
+ return ERROR(corruption_detected); /* over-read beyond lit buffer */
+ if (oLitEnd <= oend_w)
+ return ERROR(GENERIC); /* Precondition */
+
+ /* copy literals */
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, *litPtr, oend_w - op);
+ *litPtr += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oLitEnd)
+ *op++ = *(*litPtr)++;
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - base)) {
+ /* offset beyond prefix */
+ if (sequence.offset > (size_t)(oLitEnd - vBase))
+ return ERROR(corruption_detected);
+ match = dictEnd - (base - match);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currPrefixSegment */
+ {
+ size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = base;
+ }
+ }
+ while (op < oMatchEnd)
+ *op++ = *match++;
+ return sequenceLength;
+}
+
+static seq_t ZSTD_decodeSequence(seqState_t *seqState)
+{
+ seq_t seq;
+
+ U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
+ U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+
+ U32 const llBits = LL_bits[llCode];
+ U32 const mlBits = ML_bits[mlCode];
+ U32 const ofBits = ofCode;
+ U32 const totalBits = llBits + mlBits + ofBits;
+
+ static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18,
+ 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
+
+ static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41,
+ 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
+
+ static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD,
+ 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD,
+ 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
+
+ /* sequence */
+ {
+ size_t offset;
+ if (!ofCode)
+ offset = 0;
+ else {
+ offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (ZSTD_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+ }
+
+ if (ofCode <= 1) {
+ offset += (llCode == 0);
+ if (offset) {
+ size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1)
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } else {
+ offset = seqState->prevOffset[0];
+ }
+ } else {
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ }
+ seq.offset = offset;
+ }
+
+ seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
+ if (ZSTD_32bits() && (mlBits + llBits > 24))
+ BIT_reloadDStream(&seqState->DStream);
+
+ seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
+ if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+
+ /* ANS state update */
+ FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ if (ZSTD_32bits())
+ BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+
+ seq.match = NULL;
+
+ return seq;
+}
+
+FORCE_INLINE
+size_t ZSTD_execSequence(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+ const BYTE *const vBase, const BYTE *const dictEnd)
+{
+ BYTE *const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE *match = oLitEnd - sequence.offset;
+
+ /* check */
+ if (oMatchEnd > oend)
+ return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+ if (iLitEnd > litLimit)
+ return ERROR(corruption_detected); /* over-read beyond lit buffer */
+ if (oLitEnd > oend_w)
+ return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
+
+ /* copy Literals */
+ ZSTD_copy8(op, *litPtr);
+ if (sequence.litLength > 8)
+ ZSTD_wildcopy(op + 8, (*litPtr) + 8,
+ sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - base)) {
+ /* offset beyond prefix */
+ if (sequence.offset > (size_t)(oLitEnd - vBase))
+ return ERROR(corruption_detected);
+ match = dictEnd + (match - base);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currPrefixSegment */
+ {
+ size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = base;
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
+ U32 i;
+ for (i = 0; i < sequence.matchLength; ++i)
+ op[i] = match[i];
+ return sequenceLength;
+ }
+ }
+ }
+ /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
+
+ /* match within prefix */
+ if (sequence.offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
+ static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
+ int const sub2 = dec64table[sequence.offset];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[sequence.offset];
+ ZSTD_copy4(op + 4, match);
+ match -= sub2;
+ } else {
+ ZSTD_copy8(op, match);
+ }
+ op += 8;
+ match += 8;
+
+ if (oMatchEnd > oend - (16 - MINMATCH)) {
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, match, oend_w - op);
+ match += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oMatchEnd)
+ *op++ = *match++;
+ } else {
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
+ }
+ return sequenceLength;
+}
+
+static size_t ZSTD_decompressSequences(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
+{
+ const BYTE *ip = (const BYTE *)seqStart;
+ const BYTE *const iend = ip + seqSize;
+ BYTE *const ostart = (BYTE * const)dst;
+ BYTE *const oend = ostart + maxDstSize;
+ BYTE *op = ostart;
+ const BYTE *litPtr = dctx->litPtr;
+ const BYTE *const litEnd = litPtr + dctx->litSize;
+ const BYTE *const base = (const BYTE *)(dctx->base);
+ const BYTE *const vBase = (const BYTE *)(dctx->vBase);
+ const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
+ int nbSeq;
+
+ /* Build Decoding Tables */
+ {
+ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
+ if (ZSTD_isError(seqHSize))
+ return seqHSize;
+ ip += seqHSize;
+ }
+
+ /* Regen sequences */
+ if (nbSeq) {
+ seqState_t seqState;
+ dctx->fseEntropy = 1;
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqState.prevOffset[i] = dctx->entropy.rep[i];
+ }
+ CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
+ FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+ for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq;) {
+ nbSeq--;
+ {
+ seq_t const sequence = ZSTD_decodeSequence(&seqState);
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
+ if (ZSTD_isError(oneSeqSize))
+ return oneSeqSize;
+ op += oneSeqSize;
+ }
+ }
+
+ /* check if reached exact end */
+ if (nbSeq)
+ return ERROR(corruption_detected);
+ /* save reps for next block */
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
+ }
+ }
+
+ /* last literal segment */
+ {
+ size_t const lastLLSize = litEnd - litPtr;
+ if (lastLLSize > (size_t)(oend - op))
+ return ERROR(dstSize_tooSmall);
+ memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+
+ return op - ostart;
+}
+
+FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t *seqState, int const longOffsets)
+{
+ seq_t seq;
+
+ U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
+ U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
+ U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+
+ U32 const llBits = LL_bits[llCode];
+ U32 const mlBits = ML_bits[mlCode];
+ U32 const ofBits = ofCode;
+ U32 const totalBits = llBits + mlBits + ofBits;
+
+ static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18,
+ 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
+
+ static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41,
+ 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
+
+ static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD,
+ 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD,
+ 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
+
+ /* sequence */
+ {
+ size_t offset;
+ if (!ofCode)
+ offset = 0;
+ else {
+ if (longOffsets) {
+ int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
+ offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ if (ZSTD_32bits() || extraBits)
+ BIT_reloadDStream(&seqState->DStream);
+ if (extraBits)
+ offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ } else {
+ offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (ZSTD_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+ }
+ }
+
+ if (ofCode <= 1) {
+ offset += (llCode == 0);
+ if (offset) {
+ size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1)
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } else {
+ offset = seqState->prevOffset[0];
+ }
+ } else {
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ }
+ seq.offset = offset;
+ }
+
+ seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
+ if (ZSTD_32bits() && (mlBits + llBits > 24))
+ BIT_reloadDStream(&seqState->DStream);
+
+ seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
+ if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+
+ {
+ size_t const pos = seqState->pos + seq.litLength;
+ seq.match = seqState->base + pos - seq.offset; /* single memory segment */
+ if (seq.offset > pos)
+ seq.match += seqState->gotoDict; /* separate memory segment */
+ seqState->pos = pos + seq.matchLength;
+ }
+
+ /* ANS state update */
+ FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ if (ZSTD_32bits())
+ BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+
+ return seq;
+}
+
+static seq_t ZSTD_decodeSequenceLong(seqState_t *seqState, unsigned const windowSize)
+{
+ if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
+ return ZSTD_decodeSequenceLong_generic(seqState, 1);
+ } else {
+ return ZSTD_decodeSequenceLong_generic(seqState, 0);
+ }
+}
+
+FORCE_INLINE
+size_t ZSTD_execSequenceLong(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+ const BYTE *const vBase, const BYTE *const dictEnd)
+{
+ BYTE *const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE *match = sequence.match;
+
+ /* check */
+ if (oMatchEnd > oend)
+ return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+ if (iLitEnd > litLimit)
+ return ERROR(corruption_detected); /* over-read beyond lit buffer */
+ if (oLitEnd > oend_w)
+ return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
+
+ /* copy Literals */
+ ZSTD_copy8(op, *litPtr);
+ if (sequence.litLength > 8)
+ ZSTD_wildcopy(op + 8, (*litPtr) + 8,
+ sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - base)) {
+ /* offset beyond prefix */
+ if (sequence.offset > (size_t)(oLitEnd - vBase))
+ return ERROR(corruption_detected);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currPrefixSegment */
+ {
+ size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = base;
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
+ U32 i;
+ for (i = 0; i < sequence.matchLength; ++i)
+ op[i] = match[i];
+ return sequenceLength;
+ }
+ }
+ }
+ /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
+
+ /* match within prefix */
+ if (sequence.offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
+ static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
+ int const sub2 = dec64table[sequence.offset];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[sequence.offset];
+ ZSTD_copy4(op + 4, match);
+ match -= sub2;
+ } else {
+ ZSTD_copy8(op, match);
+ }
+ op += 8;
+ match += 8;
+
+ if (oMatchEnd > oend - (16 - MINMATCH)) {
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, match, oend_w - op);
+ match += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oMatchEnd)
+ *op++ = *match++;
+ } else {
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
+ }
+ return sequenceLength;
+}
+
+static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
+{
+ const BYTE *ip = (const BYTE *)seqStart;
+ const BYTE *const iend = ip + seqSize;
+ BYTE *const ostart = (BYTE * const)dst;
+ BYTE *const oend = ostart + maxDstSize;
+ BYTE *op = ostart;
+ const BYTE *litPtr = dctx->litPtr;
+ const BYTE *const litEnd = litPtr + dctx->litSize;
+ const BYTE *const base = (const BYTE *)(dctx->base);
+ const BYTE *const vBase = (const BYTE *)(dctx->vBase);
+ const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
+ unsigned const windowSize = dctx->fParams.windowSize;
+ int nbSeq;
+
+ /* Build Decoding Tables */
+ {
+ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
+ if (ZSTD_isError(seqHSize))
+ return seqHSize;
+ ip += seqHSize;
+ }
+
+ /* Regen sequences */
+ if (nbSeq) {
+#define STORED_SEQS 4
+#define STOSEQ_MASK (STORED_SEQS - 1)
+#define ADVANCED_SEQS 4
+ seq_t *sequences = (seq_t *)dctx->entropy.workspace;
+ int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
+ seqState_t seqState;
+ int seqNb;
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.workspace) >= sizeof(seq_t) * STORED_SEQS);
+ dctx->fseEntropy = 1;
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ seqState.prevOffset[i] = dctx->entropy.rep[i];
+ }
+ seqState.base = base;
+ seqState.pos = (size_t)(op - base);
+ seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
+ CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
+ FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+ /* prepare in advance */
+ for (seqNb = 0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb < seqAdvance; seqNb++) {
+ sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
+ }
+ if (seqNb < seqAdvance)
+ return ERROR(corruption_detected);
+
+ /* decode and decompress */
+ for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb < nbSeq; seqNb++) {
+ seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
+ size_t const oneSeqSize =
+ ZSTD_execSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
+ if (ZSTD_isError(oneSeqSize))
+ return oneSeqSize;
+ ZSTD_PREFETCH(sequence.match);
+ sequences[seqNb & STOSEQ_MASK] = sequence;
+ op += oneSeqSize;
+ }
+ if (seqNb < nbSeq)
+ return ERROR(corruption_detected);
+
+ /* finish queue */
+ seqNb -= seqAdvance;
+ for (; seqNb < nbSeq; seqNb++) {
+ size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
+ if (ZSTD_isError(oneSeqSize))
+ return oneSeqSize;
+ op += oneSeqSize;
+ }
+
+ /* save reps for next block */
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
+ }
+ }
+
+ /* last literal segment */
+ {
+ size_t const lastLLSize = litEnd - litPtr;
+ if (lastLLSize > (size_t)(oend - op))
+ return ERROR(dstSize_tooSmall);
+ memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+
+ return op - ostart;
+}
+
+static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{ /* blockType == blockCompressed */
+ const BYTE *ip = (const BYTE *)src;
+
+ if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+ return ERROR(srcSize_wrong);
+
+ /* Decode literals section */
+ {
+ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
+ if (ZSTD_isError(litCSize))
+ return litCSize;
+ ip += litCSize;
+ srcSize -= litCSize;
+ }
+ if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
+ /* likely because of register pressure */
+ /* if that's the correct cause, then 32-bits ARM should be affected differently */
+ /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
+ if (dctx->fParams.windowSize > (1 << 23))
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
+}
+
+static void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst)
+{
+ if (dst != dctx->previousDstEnd) { /* not contiguous */
+ dctx->dictEnd = dctx->previousDstEnd;
+ dctx->vBase = (const char *)dst - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
+ dctx->base = dst;
+ dctx->previousDstEnd = dst;
+ }
+}
+
+size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+ size_t dSize;
+ ZSTD_checkContinuity(dctx, dst);
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
+ dctx->previousDstEnd = (char *)dst + dSize;
+ return dSize;
+}
+
+/** ZSTD_insertBlock() :
+ insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
+size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize)
+{
+ ZSTD_checkContinuity(dctx, blockStart);
+ dctx->previousDstEnd = (const char *)blockStart + blockSize;
+ return blockSize;
+}
+
+size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length)
+{
+ if (length > dstCapacity)
+ return ERROR(dstSize_tooSmall);
+ memset(dst, byte, length);
+ return length;
+}
+
+/** ZSTD_findFrameCompressedSize() :
+ * compatible with legacy mode
+ * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : the compressed size of the frame starting at `src` */
+size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
+{
+ if (srcSize >= ZSTD_skippableHeaderSize && (ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+ return ZSTD_skippableHeaderSize + ZSTD_readLE32((const BYTE *)src + 4);
+ } else {
+ const BYTE *ip = (const BYTE *)src;
+ const BYTE *const ipstart = ip;
+ size_t remainingSize = srcSize;
+ ZSTD_frameParams fParams;
+
+ size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
+ if (ZSTD_isError(headerSize))
+ return headerSize;
+
+ /* Frame Header */
+ {
+ size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
+ if (ZSTD_isError(ret))
+ return ret;
+ if (ret > 0)
+ return ERROR(srcSize_wrong);
+ }
+
+ ip += headerSize;
+ remainingSize -= headerSize;
+
+ /* Loop on each block */
+ while (1) {
+ blockProperties_t blockProperties;
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+ if (ZSTD_isError(cBlockSize))
+ return cBlockSize;
+
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
+ return ERROR(srcSize_wrong);
+
+ ip += ZSTD_blockHeaderSize + cBlockSize;
+ remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
+
+ if (blockProperties.lastBlock)
+ break;
+ }
+
+ if (fParams.checksumFlag) { /* Frame content checksum */
+ if (remainingSize < 4)
+ return ERROR(srcSize_wrong);
+ ip += 4;
+ remainingSize -= 4;
+ }
+
+ return ip - ipstart;
+ }
+}
+
+/*! ZSTD_decompressFrame() :
+* @dctx must be properly initialized */
+static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr)
+{
+ const BYTE *ip = (const BYTE *)(*srcPtr);
+ BYTE *const ostart = (BYTE * const)dst;
+ BYTE *const oend = ostart + dstCapacity;
+ BYTE *op = ostart;
+ size_t remainingSize = *srcSizePtr;
+
+ /* check */
+ if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
+ return ERROR(srcSize_wrong);
+
+ /* Frame Header */
+ {
+ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
+ if (ZSTD_isError(frameHeaderSize))
+ return frameHeaderSize;
+ if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
+ return ERROR(srcSize_wrong);
+ CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
+ ip += frameHeaderSize;
+ remainingSize -= frameHeaderSize;
+ }
+
+ /* Loop on each block */
+ while (1) {
+ size_t decodedSize;
+ blockProperties_t blockProperties;
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+ if (ZSTD_isError(cBlockSize))
+ return cBlockSize;
+
+ ip += ZSTD_blockHeaderSize;
+ remainingSize -= ZSTD_blockHeaderSize;
+ if (cBlockSize > remainingSize)
+ return ERROR(srcSize_wrong);
+
+ switch (blockProperties.blockType) {
+ case bt_compressed: decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); break;
+ case bt_raw: decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); break;
+ case bt_rle: decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); break;
+ case bt_reserved:
+ default: return ERROR(corruption_detected);
+ }
+
+ if (ZSTD_isError(decodedSize))
+ return decodedSize;
+ if (dctx->fParams.checksumFlag)
+ xxh64_update(&dctx->xxhState, op, decodedSize);
+ op += decodedSize;
+ ip += cBlockSize;
+ remainingSize -= cBlockSize;
+ if (blockProperties.lastBlock)
+ break;
+ }
+
+ if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
+ U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
+ U32 checkRead;
+ if (remainingSize < 4)
+ return ERROR(checksum_wrong);
+ checkRead = ZSTD_readLE32(ip);
+ if (checkRead != checkCalc)
+ return ERROR(checksum_wrong);
+ ip += 4;
+ remainingSize -= 4;
+ }
+
+ /* Allow caller to get size read */
+ *srcPtr = ip;
+ *srcSizePtr = remainingSize;
+ return op - ostart;
+}
+
+static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict);
+static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict);
+
+static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize,
+ const ZSTD_DDict *ddict)
+{
+ void *const dststart = dst;
+
+ if (ddict) {
+ if (dict) {
+ /* programmer error, these two cases should be mutually exclusive */
+ return ERROR(GENERIC);
+ }
+
+ dict = ZSTD_DDictDictContent(ddict);
+ dictSize = ZSTD_DDictDictSize(ddict);
+ }
+
+ while (srcSize >= ZSTD_frameHeaderSize_prefix) {
+ U32 magicNumber;
+
+ magicNumber = ZSTD_readLE32(src);
+ if (magicNumber != ZSTD_MAGICNUMBER) {
+ if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t skippableSize;
+ if (srcSize < ZSTD_skippableHeaderSize)
+ return ERROR(srcSize_wrong);
+ skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
+ if (srcSize < skippableSize) {
+ return ERROR(srcSize_wrong);
+ }
+
+ src = (const BYTE *)src + skippableSize;
+ srcSize -= skippableSize;
+ continue;
+ } else {
+ return ERROR(prefix_unknown);
+ }
+ }
+
+ if (ddict) {
+ /* we were called from ZSTD_decompress_usingDDict */
+ ZSTD_refDDict(dctx, ddict);
+ } else {
+ /* this will initialize correctly with no dict if dict == NULL, so
+ * use this in all cases but ddict */
+ CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
+ }
+ ZSTD_checkContinuity(dctx, dst);
+
+ {
+ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize);
+ if (ZSTD_isError(res))
+ return res;
+ /* don't need to bounds check this, ZSTD_decompressFrame will have
+ * already */
+ dst = (BYTE *)dst + res;
+ dstCapacity -= res;
+ }
+ }
+
+ if (srcSize)
+ return ERROR(srcSize_wrong); /* input not entirely consumed */
+
+ return (BYTE *)dst - (BYTE *)dststart;
+}
+
+size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize)
+{
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
+}
+
+size_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+ return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
+}
+
+/*-**************************************
+* Advanced Streaming Decompression API
+* Bufferless and synchronous
+****************************************/
+size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx) { return dctx->expected; }
+
+ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx)
+{
+ switch (dctx->stage) {
+ default: /* should not happen */
+ case ZSTDds_getFrameHeaderSize:
+ case ZSTDds_decodeFrameHeader: return ZSTDnit_frameHeader;
+ case ZSTDds_decodeBlockHeader: return ZSTDnit_blockHeader;
+ case ZSTDds_decompressBlock: return ZSTDnit_block;
+ case ZSTDds_decompressLastBlock: return ZSTDnit_lastBlock;
+ case ZSTDds_checkChecksum: return ZSTDnit_checksum;
+ case ZSTDds_decodeSkippableHeader:
+ case ZSTDds_skipFrame: return ZSTDnit_skippableFrame;
+ }
+}
+
+int ZSTD_isSkipFrame(ZSTD_DCtx *dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */
+
+/** ZSTD_decompressContinue() :
+* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
+* or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+ /* Sanity check */
+ if (srcSize != dctx->expected)
+ return ERROR(srcSize_wrong);
+ if (dstCapacity)
+ ZSTD_checkContinuity(dctx, dst);
+
+ switch (dctx->stage) {
+ case ZSTDds_getFrameHeaderSize:
+ if (srcSize != ZSTD_frameHeaderSize_prefix)
+ return ERROR(srcSize_wrong); /* impossible */
+ if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+ dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
+ dctx->stage = ZSTDds_decodeSkippableHeader;
+ return 0;
+ }
+ dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
+ if (ZSTD_isError(dctx->headerSize))
+ return dctx->headerSize;
+ memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+ if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
+ dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
+ dctx->stage = ZSTDds_decodeFrameHeader;
+ return 0;
+ }
+ dctx->expected = 0; /* not necessary to copy more */
+
+ case ZSTDds_decodeFrameHeader:
+ memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+ CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
+ dctx->expected = ZSTD_blockHeaderSize;
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ return 0;
+
+ case ZSTDds_decodeBlockHeader: {
+ blockProperties_t bp;
+ size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
+ if (ZSTD_isError(cBlockSize))
+ return cBlockSize;
+ dctx->expected = cBlockSize;
+ dctx->bType = bp.blockType;
+ dctx->rleSize = bp.origSize;
+ if (cBlockSize) {
+ dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
+ return 0;
+ }
+ /* empty block */
+ if (bp.lastBlock) {
+ if (dctx->fParams.checksumFlag) {
+ dctx->expected = 4;
+ dctx->stage = ZSTDds_checkChecksum;
+ } else {
+ dctx->expected = 0; /* end of frame */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ }
+ } else {
+ dctx->expected = 3; /* go directly to next header */
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ }
+ return 0;
+ }
+ case ZSTDds_decompressLastBlock:
+ case ZSTDds_decompressBlock: {
+ size_t rSize;
+ switch (dctx->bType) {
+ case bt_compressed: rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); break;
+ case bt_raw: rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); break;
+ case bt_rle: rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); break;
+ case bt_reserved: /* should never happen */
+ default: return ERROR(corruption_detected);
+ }
+ if (ZSTD_isError(rSize))
+ return rSize;
+ if (dctx->fParams.checksumFlag)
+ xxh64_update(&dctx->xxhState, dst, rSize);
+
+ if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
+ if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
+ dctx->expected = 4;
+ dctx->stage = ZSTDds_checkChecksum;
+ } else {
+ dctx->expected = 0; /* ends here */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ }
+ } else {
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ dctx->expected = ZSTD_blockHeaderSize;
+ dctx->previousDstEnd = (char *)dst + rSize;
+ }
+ return rSize;
+ }
+ case ZSTDds_checkChecksum: {
+ U32 const h32 = (U32)xxh64_digest(&dctx->xxhState);
+ U32 const check32 = ZSTD_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */
+ if (check32 != h32)
+ return ERROR(checksum_wrong);
+ dctx->expected = 0;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ return 0;
+ }
+ case ZSTDds_decodeSkippableHeader: {
+ memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+ dctx->expected = ZSTD_readLE32(dctx->headerBuffer + 4);
+ dctx->stage = ZSTDds_skipFrame;
+ return 0;
+ }
+ case ZSTDds_skipFrame: {
+ dctx->expected = 0;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ return 0;
+ }
+ default:
+ return ERROR(GENERIC); /* impossible */
+ }
+}
+
+static size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+ dctx->dictEnd = dctx->previousDstEnd;
+ dctx->vBase = (const char *)dict - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
+ dctx->base = dict;
+ dctx->previousDstEnd = (const char *)dict + dictSize;
+ return 0;
+}
+
+/* ZSTD_loadEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary
+ * @return : size of entropy tables read */
+static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t *entropy, const void *const dict, size_t const dictSize)
+{
+ const BYTE *dictPtr = (const BYTE *)dict;
+ const BYTE *const dictEnd = dictPtr + dictSize;
+
+ if (dictSize <= 8)
+ return ERROR(dictionary_corrupted);
+ dictPtr += 8; /* skip header = magic + dictID */
+
+ {
+ size_t const hSize = HUF_readDTableX4_wksp(entropy->hufTable, dictPtr, dictEnd - dictPtr, entropy->workspace, sizeof(entropy->workspace));
+ if (HUF_isError(hSize))
+ return ERROR(dictionary_corrupted);
+ dictPtr += hSize;
+ }
+
+ {
+ short offcodeNCount[MaxOff + 1];
+ U32 offcodeMaxValue = MaxOff, offcodeLog;
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr);
+ if (FSE_isError(offcodeHeaderSize))
+ return ERROR(dictionary_corrupted);
+ if (offcodeLog > OffFSELog)
+ return ERROR(dictionary_corrupted);
+ CHECK_E(FSE_buildDTable_wksp(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+ dictPtr += offcodeHeaderSize;
+ }
+
+ {
+ short matchlengthNCount[MaxML + 1];
+ unsigned matchlengthMaxValue = MaxML, matchlengthLog;
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr);
+ if (FSE_isError(matchlengthHeaderSize))
+ return ERROR(dictionary_corrupted);
+ if (matchlengthLog > MLFSELog)
+ return ERROR(dictionary_corrupted);
+ CHECK_E(FSE_buildDTable_wksp(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+ dictPtr += matchlengthHeaderSize;
+ }
+
+ {
+ short litlengthNCount[MaxLL + 1];
+ unsigned litlengthMaxValue = MaxLL, litlengthLog;
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr);
+ if (FSE_isError(litlengthHeaderSize))
+ return ERROR(dictionary_corrupted);
+ if (litlengthLog > LLFSELog)
+ return ERROR(dictionary_corrupted);
+ CHECK_E(FSE_buildDTable_wksp(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+ dictPtr += litlengthHeaderSize;
+ }
+
+ if (dictPtr + 12 > dictEnd)
+ return ERROR(dictionary_corrupted);
+ {
+ int i;
+ size_t const dictContentSize = (size_t)(dictEnd - (dictPtr + 12));
+ for (i = 0; i < 3; i++) {
+ U32 const rep = ZSTD_readLE32(dictPtr);
+ dictPtr += 4;
+ if (rep == 0 || rep >= dictContentSize)
+ return ERROR(dictionary_corrupted);
+ entropy->rep[i] = rep;
+ }
+ }
+
+ return dictPtr - (const BYTE *)dict;
+}
+
+static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+ if (dictSize < 8)
+ return ZSTD_refDictContent(dctx, dict, dictSize);
+ {
+ U32 const magic = ZSTD_readLE32(dict);
+ if (magic != ZSTD_DICT_MAGIC) {
+ return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
+ }
+ }
+ dctx->dictID = ZSTD_readLE32((const char *)dict + 4);
+
+ /* load entropy tables */
+ {
+ size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
+ if (ZSTD_isError(eSize))
+ return ERROR(dictionary_corrupted);
+ dict = (const char *)dict + eSize;
+ dictSize -= eSize;
+ }
+ dctx->litEntropy = dctx->fseEntropy = 1;
+
+ /* reference dictionary content */
+ return ZSTD_refDictContent(dctx, dict, dictSize);
+}
+
+size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+ CHECK_F(ZSTD_decompressBegin(dctx));
+ if (dict && dictSize)
+ CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
+ return 0;
+}
+
+/* ====== ZSTD_DDict ====== */
+
+struct ZSTD_DDict_s {
+ void *dictBuffer;
+ const void *dictContent;
+ size_t dictSize;
+ ZSTD_entropyTables_t entropy;
+ U32 dictID;
+ U32 entropyPresent;
+ ZSTD_customMem cMem;
+}; /* typedef'd to ZSTD_DDict within "zstd.h" */
+
+size_t ZSTD_DDictWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DDict)); }
+
+static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict) { return ddict->dictContent; }
+
+static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict) { return ddict->dictSize; }
+
+static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict)
+{
+ ZSTD_decompressBegin(dstDCtx); /* init */
+ if (ddict) { /* support refDDict on NULL */
+ dstDCtx->dictID = ddict->dictID;
+ dstDCtx->base = ddict->dictContent;
+ dstDCtx->vBase = ddict->dictContent;
+ dstDCtx->dictEnd = (const BYTE *)ddict->dictContent + ddict->dictSize;
+ dstDCtx->previousDstEnd = dstDCtx->dictEnd;
+ if (ddict->entropyPresent) {
+ dstDCtx->litEntropy = 1;
+ dstDCtx->fseEntropy = 1;
+ dstDCtx->LLTptr = ddict->entropy.LLTable;
+ dstDCtx->MLTptr = ddict->entropy.MLTable;
+ dstDCtx->OFTptr = ddict->entropy.OFTable;
+ dstDCtx->HUFptr = ddict->entropy.hufTable;
+ dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
+ dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
+ dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
+ } else {
+ dstDCtx->litEntropy = 0;
+ dstDCtx->fseEntropy = 0;
+ }
+ }
+}
+
+static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict *ddict)
+{
+ ddict->dictID = 0;
+ ddict->entropyPresent = 0;
+ if (ddict->dictSize < 8)
+ return 0;
+ {
+ U32 const magic = ZSTD_readLE32(ddict->dictContent);
+ if (magic != ZSTD_DICT_MAGIC)
+ return 0; /* pure content mode */
+ }
+ ddict->dictID = ZSTD_readLE32((const char *)ddict->dictContent + 4);
+
+ /* load entropy tables */
+ CHECK_E(ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted);
+ ddict->entropyPresent = 1;
+ return 0;
+}
+
+static ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
+{
+ if (!customMem.customAlloc || !customMem.customFree)
+ return NULL;
+
+ {
+ ZSTD_DDict *const ddict = (ZSTD_DDict *)ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
+ if (!ddict)
+ return NULL;
+ ddict->cMem = customMem;
+
+ if ((byReference) || (!dict) || (!dictSize)) {
+ ddict->dictBuffer = NULL;
+ ddict->dictContent = dict;
+ } else {
+ void *const internalBuffer = ZSTD_malloc(dictSize, customMem);
+ if (!internalBuffer) {
+ ZSTD_freeDDict(ddict);
+ return NULL;
+ }
+ memcpy(internalBuffer, dict, dictSize);
+ ddict->dictBuffer = internalBuffer;
+ ddict->dictContent = internalBuffer;
+ }
+ ddict->dictSize = dictSize;
+ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+ /* parse dictionary content */
+ {
+ size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
+ if (ZSTD_isError(errorCode)) {
+ ZSTD_freeDDict(ddict);
+ return NULL;
+ }
+ }
+
+ return ddict;
+ }
+}
+
+/*! ZSTD_initDDict() :
+* Create a digested dictionary, to start decompression without startup delay.
+* `dict` content is copied inside DDict.
+* Consequently, `dict` can be released after `ZSTD_DDict` creation */
+ZSTD_DDict *ZSTD_initDDict(const void *dict, size_t dictSize, void *workspace, size_t workspaceSize)
+{
+ ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+ return ZSTD_createDDict_advanced(dict, dictSize, 1, stackMem);
+}
+
+size_t ZSTD_freeDDict(ZSTD_DDict *ddict)
+{
+ if (ddict == NULL)
+ return 0; /* support free on NULL */
+ {
+ ZSTD_customMem const cMem = ddict->cMem;
+ ZSTD_free(ddict->dictBuffer, cMem);
+ ZSTD_free(ddict, cMem);
+ return 0;
+ }
+}
+
+/*! ZSTD_getDictID_fromDict() :
+ * Provides the dictID stored within dictionary.
+ * if @return == 0, the dictionary is not conformant with Zstandard specification.
+ * It can still be loaded, but as a content-only dictionary. */
+unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize)
+{
+ if (dictSize < 8)
+ return 0;
+ if (ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC)
+ return 0;
+ return ZSTD_readLE32((const char *)dict + 4);
+}
+
+/*! ZSTD_getDictID_fromDDict() :
+ * Provides the dictID of the dictionary loaded into `ddict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict)
+{
+ if (ddict == NULL)
+ return 0;
+ return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
+}
+
+/*! ZSTD_getDictID_fromFrame() :
+ * Provides the dictID required to decompressed the frame stored within `src`.
+ * If @return == 0, the dictID could not be decoded.
+ * This could for one of the following reasons :
+ * - The frame does not require a dictionary to be decoded (most common case).
+ * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
+ * Note : this use case also happens when using a non-conformant dictionary.
+ * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
+ * - This is not a Zstandard frame.
+ * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
+unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize)
+{
+ ZSTD_frameParams zfp = {0, 0, 0, 0};
+ size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
+ if (ZSTD_isError(hError))
+ return 0;
+ return zfp.dictID;
+}
+
+/*! ZSTD_decompress_usingDDict() :
+* Decompression using a pre-digested Dictionary
+* Use dictionary without significant overhead. */
+size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict)
+{
+ /* pass content and size in case legacy frames are encountered */
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, NULL, 0, ddict);
+}
+
+/*=====================================
+* Streaming decompression
+*====================================*/
+
+typedef enum { zdss_init, zdss_loadHeader, zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
+
+/* *** Resource management *** */
+struct ZSTD_DStream_s {
+ ZSTD_DCtx *dctx;
+ ZSTD_DDict *ddictLocal;
+ const ZSTD_DDict *ddict;
+ ZSTD_frameParams fParams;
+ ZSTD_dStreamStage stage;
+ char *inBuff;
+ size_t inBuffSize;
+ size_t inPos;
+ size_t maxWindowSize;
+ char *outBuff;
+ size_t outBuffSize;
+ size_t outStart;
+ size_t outEnd;
+ size_t blockSize;
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
+ size_t lhSize;
+ ZSTD_customMem customMem;
+ void *legacyContext;
+ U32 previousLegacyVersion;
+ U32 legacyVersion;
+ U32 hostageByte;
+}; /* typedef'd to ZSTD_DStream within "zstd.h" */
+
+size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize)
+{
+ size_t const blockSize = MIN(maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+ size_t const inBuffSize = blockSize;
+ size_t const outBuffSize = maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+ return ZSTD_DCtxWorkspaceBound() + ZSTD_ALIGN(sizeof(ZSTD_DStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize);
+}
+
+static ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem)
+{
+ ZSTD_DStream *zds;
+
+ if (!customMem.customAlloc || !customMem.customFree)
+ return NULL;
+
+ zds = (ZSTD_DStream *)ZSTD_malloc(sizeof(ZSTD_DStream), customMem);
+ if (zds == NULL)
+ return NULL;
+ memset(zds, 0, sizeof(ZSTD_DStream));
+ memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
+ zds->dctx = ZSTD_createDCtx_advanced(customMem);
+ if (zds->dctx == NULL) {
+ ZSTD_freeDStream(zds);
+ return NULL;
+ }
+ zds->stage = zdss_init;
+ zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+ return zds;
+}
+
+ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t workspaceSize)
+{
+ ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+ ZSTD_DStream *zds = ZSTD_createDStream_advanced(stackMem);
+ if (!zds) {
+ return NULL;
+ }
+
+ zds->maxWindowSize = maxWindowSize;
+ zds->stage = zdss_loadHeader;
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+ ZSTD_freeDDict(zds->ddictLocal);
+ zds->ddictLocal = NULL;
+ zds->ddict = zds->ddictLocal;
+ zds->legacyVersion = 0;
+ zds->hostageByte = 0;
+
+ {
+ size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+ size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+
+ zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
+ zds->inBuffSize = blockSize;
+ zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
+ zds->outBuffSize = neededOutSize;
+ if (zds->inBuff == NULL || zds->outBuff == NULL) {
+ ZSTD_freeDStream(zds);
+ return NULL;
+ }
+ }
+ return zds;
+}
+
+ZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize, const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize)
+{
+ ZSTD_DStream *zds = ZSTD_initDStream(maxWindowSize, workspace, workspaceSize);
+ if (zds) {
+ zds->ddict = ddict;
+ }
+ return zds;
+}
+
+size_t ZSTD_freeDStream(ZSTD_DStream *zds)
+{
+ if (zds == NULL)
+ return 0; /* support free on null */
+ {
+ ZSTD_customMem const cMem = zds->customMem;
+ ZSTD_freeDCtx(zds->dctx);
+ zds->dctx = NULL;
+ ZSTD_freeDDict(zds->ddictLocal);
+ zds->ddictLocal = NULL;
+ ZSTD_free(zds->inBuff, cMem);
+ zds->inBuff = NULL;
+ ZSTD_free(zds->outBuff, cMem);
+ zds->outBuff = NULL;
+ ZSTD_free(zds, cMem);
+ return 0;
+ }
+}
+
+/* *** Initialization *** */
+
+size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
+size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
+
+size_t ZSTD_resetDStream(ZSTD_DStream *zds)
+{
+ zds->stage = zdss_loadHeader;
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+ zds->legacyVersion = 0;
+ zds->hostageByte = 0;
+ return ZSTD_frameHeaderSize_prefix;
+}
+
+/* ***** Decompression ***** */
+
+ZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+ size_t const length = MIN(dstCapacity, srcSize);
+ memcpy(dst, src, length);
+ return length;
+}
+
+size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
+{
+ const char *const istart = (const char *)(input->src) + input->pos;
+ const char *const iend = (const char *)(input->src) + input->size;
+ const char *ip = istart;
+ char *const ostart = (char *)(output->dst) + output->pos;
+ char *const oend = (char *)(output->dst) + output->size;
+ char *op = ostart;
+ U32 someMoreWork = 1;
+
+ while (someMoreWork) {
+ switch (zds->stage) {
+ case zdss_init:
+ ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
+ /* fall-through */
+
+ case zdss_loadHeader: {
+ size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
+ if (ZSTD_isError(hSize))
+ return hSize;
+ if (hSize != 0) { /* need more input */
+ size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
+ if (toLoad > (size_t)(iend - ip)) { /* not enough input to load full header */
+ memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip);
+ zds->lhSize += iend - ip;
+ input->pos = input->size;
+ return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) +
+ ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
+ }
+ memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad);
+ zds->lhSize = hSize;
+ ip += toLoad;
+ break;
+ }
+
+ /* check for single-pass mode opportunity */
+ if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
+ && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) {
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart);
+ if (cSize <= (size_t)(iend - istart)) {
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict);
+ if (ZSTD_isError(decompressedSize))
+ return decompressedSize;
+ ip = istart + cSize;
+ op += decompressedSize;
+ zds->dctx->expected = 0;
+ zds->stage = zdss_init;
+ someMoreWork = 0;
+ break;
+ }
+ }
+
+ /* Consume header */
+ ZSTD_refDDict(zds->dctx, zds->ddict);
+ {
+ size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
+ CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
+ {
+ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size));
+ }
+ }
+
+ zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
+ if (zds->fParams.windowSize > zds->maxWindowSize)
+ return ERROR(frameParameter_windowTooLarge);
+
+ /* Buffers are preallocated, but double check */
+ {
+ size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+ size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+ if (zds->inBuffSize < blockSize) {
+ return ERROR(GENERIC);
+ }
+ if (zds->outBuffSize < neededOutSize) {
+ return ERROR(GENERIC);
+ }
+ zds->blockSize = blockSize;
+ }
+ zds->stage = zdss_read;
+ }
+ /* pass-through */
+
+ case zdss_read: {
+ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ if (neededInSize == 0) { /* end of frame */
+ zds->stage = zdss_init;
+ someMoreWork = 0;
+ break;
+ }
+ if ((size_t)(iend - ip) >= neededInSize) { /* decode directly from src */
+ const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+ size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart,
+ (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), ip, neededInSize);
+ if (ZSTD_isError(decodedSize))
+ return decodedSize;
+ ip += neededInSize;
+ if (!decodedSize && !isSkipFrame)
+ break; /* this was just a header */
+ zds->outEnd = zds->outStart + decodedSize;
+ zds->stage = zdss_flush;
+ break;
+ }
+ if (ip == iend) {
+ someMoreWork = 0;
+ break;
+ } /* no more input */
+ zds->stage = zdss_load;
+ /* pass-through */
+ }
+
+ case zdss_load: {
+ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
+ size_t loadedSize;
+ if (toLoad > zds->inBuffSize - zds->inPos)
+ return ERROR(corruption_detected); /* should never happen */
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip);
+ ip += loadedSize;
+ zds->inPos += loadedSize;
+ if (loadedSize < toLoad) {
+ someMoreWork = 0;
+ break;
+ } /* not enough input, wait for more */
+
+ /* decode loaded input */
+ {
+ const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+ size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
+ zds->inBuff, neededInSize);
+ if (ZSTD_isError(decodedSize))
+ return decodedSize;
+ zds->inPos = 0; /* input is consumed */
+ if (!decodedSize && !isSkipFrame) {
+ zds->stage = zdss_read;
+ break;
+ } /* this was just a header */
+ zds->outEnd = zds->outStart + decodedSize;
+ zds->stage = zdss_flush;
+ /* pass-through */
+ }
+ }
+
+ case zdss_flush: {
+ size_t const toFlushSize = zds->outEnd - zds->outStart;
+ size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize);
+ op += flushedSize;
+ zds->outStart += flushedSize;
+ if (flushedSize == toFlushSize) { /* flush completed */
+ zds->stage = zdss_read;
+ if (zds->outStart + zds->blockSize > zds->outBuffSize)
+ zds->outStart = zds->outEnd = 0;
+ break;
+ }
+ /* cannot complete flush */
+ someMoreWork = 0;
+ break;
+ }
+ default:
+ return ERROR(GENERIC); /* impossible */
+ }
+ }
+
+ /* result */
+ input->pos += (size_t)(ip - istart);
+ output->pos += (size_t)(op - ostart);
+ {
+ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+ if (!nextSrcSizeHint) { /* frame fully decoded */
+ if (zds->outEnd == zds->outStart) { /* output fully flushed */
+ if (zds->hostageByte) {
+ if (input->pos >= input->size) {
+ zds->stage = zdss_read;
+ return 1;
+ } /* can't release hostage (not present) */
+ input->pos++; /* release hostage */
+ }
+ return 0;
+ }
+ if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
+ input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
+ zds->hostageByte = 1;
+ }
+ return 1;
+ }
+ nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
+ if (zds->inPos > nextSrcSizeHint)
+ return ERROR(GENERIC); /* should never happen */
+ nextSrcSizeHint -= zds->inPos; /* already loaded*/
+ return nextSrcSizeHint;
+ }
+}
+
+EXPORT_SYMBOL(ZSTD_DCtxWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDCtx);
+EXPORT_SYMBOL(ZSTD_decompressDCtx);
+EXPORT_SYMBOL(ZSTD_decompress_usingDict);
+
+EXPORT_SYMBOL(ZSTD_DDictWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDDict);
+EXPORT_SYMBOL(ZSTD_decompress_usingDDict);
+
+EXPORT_SYMBOL(ZSTD_DStreamWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDStream);
+EXPORT_SYMBOL(ZSTD_initDStream_usingDDict);
+EXPORT_SYMBOL(ZSTD_resetDStream);
+EXPORT_SYMBOL(ZSTD_decompressStream);
+EXPORT_SYMBOL(ZSTD_DStreamInSize);
+EXPORT_SYMBOL(ZSTD_DStreamOutSize);
+
+EXPORT_SYMBOL(ZSTD_findFrameCompressedSize);
+EXPORT_SYMBOL(ZSTD_getFrameContentSize);
+EXPORT_SYMBOL(ZSTD_findDecompressedSize);
+
+EXPORT_SYMBOL(ZSTD_isFrame);
+EXPORT_SYMBOL(ZSTD_getDictID_fromDict);
+EXPORT_SYMBOL(ZSTD_getDictID_fromDDict);
+EXPORT_SYMBOL(ZSTD_getDictID_fromFrame);
+
+EXPORT_SYMBOL(ZSTD_getFrameParams);
+EXPORT_SYMBOL(ZSTD_decompressBegin);
+EXPORT_SYMBOL(ZSTD_decompressBegin_usingDict);
+EXPORT_SYMBOL(ZSTD_copyDCtx);
+EXPORT_SYMBOL(ZSTD_nextSrcSizeToDecompress);
+EXPORT_SYMBOL(ZSTD_decompressContinue);
+EXPORT_SYMBOL(ZSTD_nextInputType);
+
+EXPORT_SYMBOL(ZSTD_decompressBlock);
+EXPORT_SYMBOL(ZSTD_insertBlock);
diff --git a/lib/zstd/entropy_common.c b/lib/zstd/entropy_common.c
new file mode 100644
index 00000000..071fef99
--- /dev/null
+++ b/lib/zstd/entropy_common.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
+/*
+ * Common functions of New Generation Entropy library
+ * Copyright (C) 2016, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* *************************************
+* Dependencies
+***************************************/
+#include "error_private.h" /* ERR_*, ERROR */
+#include "fse.h"
+#include "huf.h"
+#include "mem.h"
+
+/*=== Version ===*/
+unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
+
+/*=== Error Management ===*/
+unsigned FSE_isError(size_t code) { return ERR_isError(code); }
+
+unsigned HUF_isError(size_t code) { return ERR_isError(code); }
+
+/*-**************************************************************
+* FSE NCount encoding-decoding
+****************************************************************/
+size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSVPtr, unsigned *tableLogPtr, const void *headerBuffer, size_t hbSize)
+{
+ const BYTE *const istart = (const BYTE *)headerBuffer;
+ const BYTE *const iend = istart + hbSize;
+ const BYTE *ip = istart;
+ int nbBits;
+ int remaining;
+ int threshold;
+ U32 bitStream;
+ int bitCount;
+ unsigned charnum = 0;
+ int previous0 = 0;
+
+ if (hbSize < 4)
+ return ERROR(srcSize_wrong);
+ bitStream = ZSTD_readLE32(ip);
+ nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
+ if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX)
+ return ERROR(tableLog_tooLarge);
+ bitStream >>= 4;
+ bitCount = 4;
+ *tableLogPtr = nbBits;
+ remaining = (1 << nbBits) + 1;
+ threshold = 1 << nbBits;
+ nbBits++;
+
+ while ((remaining > 1) & (charnum <= *maxSVPtr)) {
+ if (previous0) {
+ unsigned n0 = charnum;
+ while ((bitStream & 0xFFFF) == 0xFFFF) {
+ n0 += 24;
+ if (ip < iend - 5) {
+ ip += 2;
+ bitStream = ZSTD_readLE32(ip) >> bitCount;
+ } else {
+ bitStream >>= 16;
+ bitCount += 16;
+ }
+ }
+ while ((bitStream & 3) == 3) {
+ n0 += 3;
+ bitStream >>= 2;
+ bitCount += 2;
+ }
+ n0 += bitStream & 3;
+ bitCount += 2;
+ if (n0 > *maxSVPtr)
+ return ERROR(maxSymbolValue_tooSmall);
+ while (charnum < n0)
+ normalizedCounter[charnum++] = 0;
+ if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
+ ip += bitCount >> 3;
+ bitCount &= 7;
+ bitStream = ZSTD_readLE32(ip) >> bitCount;
+ } else {
+ bitStream >>= 2;
+ }
+ }
+ {
+ int const max = (2 * threshold - 1) - remaining;
+ int count;
+
+ if ((bitStream & (threshold - 1)) < (U32)max) {
+ count = bitStream & (threshold - 1);
+ bitCount += nbBits - 1;
+ } else {
+ count = bitStream & (2 * threshold - 1);
+ if (count >= threshold)
+ count -= max;
+ bitCount += nbBits;
+ }
+
+ count--; /* extra accuracy */
+ remaining -= count < 0 ? -count : count; /* -1 means +1 */
+ normalizedCounter[charnum++] = (short)count;
+ previous0 = !count;
+ while (remaining < threshold) {
+ nbBits--;
+ threshold >>= 1;
+ }
+
+ if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
+ ip += bitCount >> 3;
+ bitCount &= 7;
+ } else {
+ bitCount -= (int)(8 * (iend - 4 - ip));
+ ip = iend - 4;
+ }
+ bitStream = ZSTD_readLE32(ip) >> (bitCount & 31);
+ }
+ } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
+ if (remaining != 1)
+ return ERROR(corruption_detected);
+ if (bitCount > 32)
+ return ERROR(corruption_detected);
+ *maxSVPtr = charnum - 1;
+
+ ip += (bitCount + 7) >> 3;
+ return ip - istart;
+}
+
+/*! HUF_readStats() :
+ Read compact Huffman tree, saved by HUF_writeCTable().
+ `huffWeight` is destination buffer.
+ `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
+ @return : size read from `src` , or an error Code .
+ Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
+*/
+size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+ U32 weightTotal;
+ const BYTE *ip = (const BYTE *)src;
+ size_t iSize;
+ size_t oSize;
+
+ if (!srcSize)
+ return ERROR(srcSize_wrong);
+ iSize = ip[0];
+ /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
+
+ if (iSize >= 128) { /* special header */
+ oSize = iSize - 127;
+ iSize = ((oSize + 1) / 2);
+ if (iSize + 1 > srcSize)
+ return ERROR(srcSize_wrong);
+ if (oSize >= hwSize)
+ return ERROR(corruption_detected);
+ ip += 1;
+ {
+ U32 n;
+ for (n = 0; n < oSize; n += 2) {
+ huffWeight[n] = ip[n / 2] >> 4;
+ huffWeight[n + 1] = ip[n / 2] & 15;
+ }
+ }
+ } else { /* header compressed with FSE (normal case) */
+ if (iSize + 1 > srcSize)
+ return ERROR(srcSize_wrong);
+ oSize = FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, 6, workspace, workspaceSize); /* max (hwSize-1) values decoded, as last one is implied */
+ if (FSE_isError(oSize))
+ return oSize;
+ }
+
+ /* collect weight stats */
+ memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
+ weightTotal = 0;
+ {
+ U32 n;
+ for (n = 0; n < oSize; n++) {
+ if (huffWeight[n] >= HUF_TABLELOG_MAX)
+ return ERROR(corruption_detected);
+ rankStats[huffWeight[n]]++;
+ weightTotal += (1 << huffWeight[n]) >> 1;
+ }
+ }
+ if (weightTotal == 0)
+ return ERROR(corruption_detected);
+
+ /* get last non-null symbol weight (implied, total must be 2^n) */
+ {
+ U32 const tableLog = BIT_highbit32(weightTotal) + 1;
+ if (tableLog > HUF_TABLELOG_MAX)
+ return ERROR(corruption_detected);
+ *tableLogPtr = tableLog;
+ /* determine last weight */
+ {
+ U32 const total = 1 << tableLog;
+ U32 const rest = total - weightTotal;
+ U32 const verif = 1 << BIT_highbit32(rest);
+ U32 const lastWeight = BIT_highbit32(rest) + 1;
+ if (verif != rest)
+ return ERROR(corruption_detected); /* last value must be a clean power of 2 */
+ huffWeight[oSize] = (BYTE)lastWeight;
+ rankStats[lastWeight]++;
+ }
+ }
+
+ /* check tree construction validity */
+ if ((rankStats[1] < 2) || (rankStats[1] & 1))
+ return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
+
+ /* results */
+ *nbSymbolsPtr = (U32)(oSize + 1);
+ return iSize + 1;
+}
diff --git a/lib/zstd/error_private.h b/lib/zstd/error_private.h
new file mode 100644
index 00000000..d4824e25
--- /dev/null
+++ b/lib/zstd/error_private.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+/* Note : this module is expected to remain private, do not expose it */
+
+#ifndef ERROR_H_MODULE
+#define ERROR_H_MODULE
+
+/* ****************************************
+* Dependencies
+******************************************/
+#include <linux/types.h> /* size_t */
+#include <linux/zstd.h> /* enum list */
+
+/* ****************************************
+* Compiler-specific
+******************************************/
+#define ERR_STATIC static __attribute__((unused))
+
+/*-****************************************
+* Customization (error_public.h)
+******************************************/
+typedef ZSTD_ErrorCode ERR_enum;
+#define PREFIX(name) ZSTD_error_##name
+
+/*-****************************************
+* Error codes handling
+******************************************/
+#define ERROR(name) ((size_t)-PREFIX(name))
+
+ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
+
+ERR_STATIC ERR_enum ERR_getErrorCode(size_t code)
+{
+ if (!ERR_isError(code))
+ return (ERR_enum)0;
+ return (ERR_enum)(0 - code);
+}
+
+#endif /* ERROR_H_MODULE */
diff --git a/lib/zstd/fse.h b/lib/zstd/fse.h
new file mode 100644
index 00000000..42f80ff7
--- /dev/null
+++ b/lib/zstd/fse.h
@@ -0,0 +1,545 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
+/*
+ * FSE : Finite State Entropy codec
+ * Public Prototypes declaration
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef FSE_H
+#define FSE_H
+
+/*-*****************************************
+* Dependencies
+******************************************/
+#include <linux/types.h> /* size_t, ptrdiff_t */
+
+/*-*****************************************
+* FSE_PUBLIC_API : control library symbols visibility
+******************************************/
+#define FSE_PUBLIC_API
+
+/*------ Version ------*/
+#define FSE_VERSION_MAJOR 0
+#define FSE_VERSION_MINOR 9
+#define FSE_VERSION_RELEASE 0
+
+#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
+#define FSE_QUOTE(str) #str
+#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
+#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
+
+#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR * 100 * 100 + FSE_VERSION_MINOR * 100 + FSE_VERSION_RELEASE)
+FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
+
+/*-*****************************************
+* Tool functions
+******************************************/
+FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
+
+/* Error Management */
+FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
+
+/*-*****************************************
+* FSE detailed API
+******************************************/
+/*!
+FSE_compress() does the following:
+1. count symbol occurrence from source[] into table count[]
+2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
+3. save normalized counters to memory buffer using writeNCount()
+4. build encoding table 'CTable' from normalized counters
+5. encode the data stream using encoding table 'CTable'
+
+FSE_decompress() does the following:
+1. read normalized counters with readNCount()
+2. build decoding table 'DTable' from normalized counters
+3. decode the data stream using decoding table 'DTable'
+
+The following API allows targeting specific sub-functions for advanced tasks.
+For example, it's possible to compress several blocks using the same 'CTable',
+or to save and provide normalized distribution using external method.
+*/
+
+/* *** COMPRESSION *** */
+/*! FSE_optimalTableLog():
+ dynamically downsize 'tableLog' when conditions are met.
+ It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
+ @return : recommended tableLog (necessarily <= 'maxTableLog') */
+FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+
+/*! FSE_normalizeCount():
+ normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
+ 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
+ @return : tableLog,
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t srcSize, unsigned maxSymbolValue);
+
+/*! FSE_NCountWriteBound():
+ Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
+ Typically useful for allocation purpose. */
+FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
+
+/*! FSE_writeNCount():
+ Compactly save 'normalizedCounter' into 'buffer'.
+ @return : size of the compressed table,
+ or an errorCode, which can be tested using FSE_isError(). */
+FSE_PUBLIC_API size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
+
+/*! Constructor and Destructor of FSE_CTable.
+ Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
+typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
+
+/*! FSE_compress_usingCTable():
+ Compress `src` using `ct` into `dst` which must be already allocated.
+ @return : size of compressed data (<= `dstCapacity`),
+ or 0 if compressed data could not fit into `dst`,
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_compress_usingCTable(void *dst, size_t dstCapacity, const void *src, size_t srcSize, const FSE_CTable *ct);
+
+/*!
+Tutorial :
+----------
+The first step is to count all symbols. FSE_count() does this job very fast.
+Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
+'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
+maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
+FSE_count() will return the number of occurrence of the most frequent symbol.
+This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+The next step is to normalize the frequencies.
+FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
+It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
+You can use 'tableLog'==0 to mean "use default tableLog value".
+If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
+which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
+
+The result of FSE_normalizeCount() will be saved into a table,
+called 'normalizedCounter', which is a table of signed short.
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
+The return value is tableLog if everything proceeded as expected.
+It is 0 if there is a single symbol within distribution.
+If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
+'buffer' must be already allocated.
+For guaranteed success, buffer size must be at least FSE_headerBound().
+The result of the function is the number of bytes written into 'buffer'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
+
+'normalizedCounter' can then be used to create the compression table 'CTable'.
+The space required by 'CTable' must be already allocated, using FSE_createCTable().
+You can then use FSE_buildCTable() to fill 'CTable'.
+If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
+
+'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
+Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
+The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
+If it returns '0', compressed data could not fit into 'dst'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+*/
+
+/* *** DECOMPRESSION *** */
+
+/*! FSE_readNCount():
+ Read compactly saved 'normalizedCounter' from 'rBuffer'.
+ @return : size read from 'rBuffer',
+ or an errorCode, which can be tested using FSE_isError().
+ maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
+FSE_PUBLIC_API size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize);
+
+/*! Constructor and Destructor of FSE_DTable.
+ Note that its size depends on 'tableLog' */
+typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
+
+/*! FSE_buildDTable():
+ Builds 'dt', which must be already allocated, using FSE_createDTable().
+ return : 0, or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize);
+
+/*! FSE_decompress_usingDTable():
+ Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
+ into `dst` which must be already allocated.
+ @return : size of regenerated data (necessarily <= `dstCapacity`),
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt);
+
+/*!
+Tutorial :
+----------
+(Note : these functions only decompress FSE-compressed blocks.
+ If block is uncompressed, use memcpy() instead
+ If block is a single repeated byte, use memset() instead )
+
+The first step is to obtain the normalized frequencies of symbols.
+This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
+In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
+or size the table to handle worst case situations (typically 256).
+FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
+The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
+Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
+This is performed by the function FSE_buildDTable().
+The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
+`cSrcSize` must be strictly correct, otherwise decompression will fail.
+FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
+If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
+*/
+
+/* *** Dependency *** */
+#include "bitstream.h"
+
+/* *****************************************
+* Static allocation
+*******************************************/
+/* FSE buffer bounds */
+#define FSE_NCOUNTBOUND 512
+#define FSE_BLOCKBOUND(size) (size + (size >> 7))
+#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
+#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1 << (maxTableLog - 1)) + ((maxSymbolValue + 1) * 2))
+#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog))
+
+/* *****************************************
+* FSE advanced API
+*******************************************/
+/* FSE_count_wksp() :
+ * Same as FSE_count(), but using an externally provided scratch buffer.
+ * `workSpace` size must be table of >= `1024` unsigned
+ */
+size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace);
+
+/* FSE_countFast_wksp() :
+ * Same as FSE_countFast(), but using an externally provided scratch buffer.
+ * `workSpace` must be a table of minimum `1024` unsigned
+ */
+size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize, unsigned *workSpace);
+
+/*! FSE_count_simple
+ * Same as FSE_countFast(), but does not use any additional memory (not even on stack).
+ * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
+*/
+size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize);
+
+unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
+/**< same as FSE_optimalTableLog(), which used `minus==2` */
+
+size_t FSE_buildCTable_raw(FSE_CTable *ct, unsigned nbBits);
+/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
+
+size_t FSE_buildCTable_rle(FSE_CTable *ct, unsigned char symbolValue);
+/**< build a fake FSE_CTable, designed to compress always the same symbolValue */
+
+/* FSE_buildCTable_wksp() :
+ * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
+ * `wkspSize` must be >= `(1<<tableLog)`.
+ */
+size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize);
+
+size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits);
+/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
+
+size_t FSE_buildDTable_rle(FSE_DTable *dt, unsigned char symbolValue);
+/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
+
+size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize);
+/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
+
+/* *****************************************
+* FSE symbol compression API
+*******************************************/
+/*!
+ This API consists of small unitary functions, which highly benefit from being inlined.
+ Hence their body are included in next section.
+*/
+typedef struct {
+ ptrdiff_t value;
+ const void *stateTable;
+ const void *symbolTT;
+ unsigned stateLog;
+} FSE_CState_t;
+
+static void FSE_initCState(FSE_CState_t *CStatePtr, const FSE_CTable *ct);
+
+static void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *CStatePtr, unsigned symbol);
+
+static void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *CStatePtr);
+
+/**<
+These functions are inner components of FSE_compress_usingCTable().
+They allow the creation of custom streams, mixing multiple tables and bit sources.
+
+A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
+So the first symbol you will encode is the last you will decode, like a LIFO stack.
+
+You will need a few variables to track your CStream. They are :
+
+FSE_CTable ct; // Provided by FSE_buildCTable()
+BIT_CStream_t bitStream; // bitStream tracking structure
+FSE_CState_t state; // State tracking structure (can have several)
+
+
+The first thing to do is to init bitStream and state.
+ size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
+ FSE_initCState(&state, ct);
+
+Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
+You can then encode your input data, byte after byte.
+FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
+Remember decoding will be done in reverse direction.
+ FSE_encodeByte(&bitStream, &state, symbol);
+
+At any time, you can also add any bit sequence.
+Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
+ BIT_addBits(&bitStream, bitField, nbBits);
+
+The above methods don't commit data to memory, they just store it into local register, for speed.
+Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+Writing data to memory is a manual operation, performed by the flushBits function.
+ BIT_flushBits(&bitStream);
+
+Your last FSE encoding operation shall be to flush your last state value(s).
+ FSE_flushState(&bitStream, &state);
+
+Finally, you must close the bitStream.
+The function returns the size of CStream in bytes.
+If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
+If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
+ size_t size = BIT_closeCStream(&bitStream);
+*/
+
+/* *****************************************
+* FSE symbol decompression API
+*******************************************/
+typedef struct {
+ size_t state;
+ const void *table; /* precise table may vary, depending on U16 */
+} FSE_DState_t;
+
+static void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt);
+
+static unsigned char FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
+
+static unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr);
+
+/**<
+Let's now decompose FSE_decompress_usingDTable() into its unitary components.
+You will decode FSE-encoded symbols from the bitStream,
+and also any other bitFields you put in, **in reverse order**.
+
+You will need a few variables to track your bitStream. They are :
+
+BIT_DStream_t DStream; // Stream context
+FSE_DState_t DState; // State context. Multiple ones are possible
+FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
+
+The first thing to do is to init the bitStream.
+ errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
+
+You should then retrieve your initial state(s)
+(in reverse flushing order if you have several ones) :
+ errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
+
+You can then decode your data, symbol after symbol.
+For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
+Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
+ unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
+
+You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
+Note : maximum allowed nbBits is 25, for 32-bits compatibility
+ size_t bitField = BIT_readBits(&DStream, nbBits);
+
+All above operations only read from local register (which size depends on size_t).
+Refueling the register from memory is manually performed by the reload method.
+ endSignal = FSE_reloadDStream(&DStream);
+
+BIT_reloadDStream() result tells if there is still some more data to read from DStream.
+BIT_DStream_unfinished : there is still some data left into the DStream.
+BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
+BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
+BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
+
+When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
+to properly detect the exact end of stream.
+After each decoded symbol, check if DStream is fully consumed using this simple test :
+ BIT_reloadDStream(&DStream) >= BIT_DStream_completed
+
+When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
+Checking if DStream has reached its end is performed by :
+ BIT_endOfDStream(&DStream);
+Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
+ FSE_endOfDState(&DState);
+*/
+
+/* *****************************************
+* FSE unsafe API
+*******************************************/
+static unsigned char FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
+/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
+
+/* *****************************************
+* Implementation of inlined functions
+*******************************************/
+typedef struct {
+ int deltaFindState;
+ U32 deltaNbBits;
+} FSE_symbolCompressionTransform; /* total 8 bytes */
+
+ZSTD_STATIC void FSE_initCState(FSE_CState_t *statePtr, const FSE_CTable *ct)
+{
+ const void *ptr = ct;
+ const U16 *u16ptr = (const U16 *)ptr;
+ const U32 tableLog = ZSTD_read16(ptr);
+ statePtr->value = (ptrdiff_t)1 << tableLog;
+ statePtr->stateTable = u16ptr + 2;
+ statePtr->symbolTT = ((const U32 *)ct + 1 + (tableLog ? (1 << (tableLog - 1)) : 1));
+ statePtr->stateLog = tableLog;
+}
+
+/*! FSE_initCState2() :
+* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
+* uses the smallest state value possible, saving the cost of this symbol */
+ZSTD_STATIC void FSE_initCState2(FSE_CState_t *statePtr, const FSE_CTable *ct, U32 symbol)
+{
+ FSE_initCState(statePtr, ct);
+ {
+ const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
+ const U16 *stateTable = (const U16 *)(statePtr->stateTable);
+ U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1 << 15)) >> 16);
+ statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
+ statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+ }
+}
+
+ZSTD_STATIC void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *statePtr, U32 symbol)
+{
+ const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
+ const U16 *const stateTable = (const U16 *)(statePtr->stateTable);
+ U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
+ BIT_addBits(bitC, statePtr->value, nbBitsOut);
+ statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+}
+
+ZSTD_STATIC void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *statePtr)
+{
+ BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
+ BIT_flushBits(bitC);
+}
+
+/* ====== Decompression ====== */
+
+typedef struct {
+ U16 tableLog;
+ U16 fastMode;
+} FSE_DTableHeader; /* sizeof U32 */
+
+typedef struct {
+ unsigned short newState;
+ unsigned char symbol;
+ unsigned char nbBits;
+} FSE_decode_t; /* size == U32 */
+
+ZSTD_STATIC void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt)
+{
+ const void *ptr = dt;
+ const FSE_DTableHeader *const DTableH = (const FSE_DTableHeader *)ptr;
+ DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+ BIT_reloadDStream(bitD);
+ DStatePtr->table = dt + 1;
+}
+
+ZSTD_STATIC BYTE FSE_peekSymbol(const FSE_DState_t *DStatePtr)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+ return DInfo.symbol;
+}
+
+ZSTD_STATIC void FSE_updateState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+ DStatePtr->state = DInfo.newState + lowBits;
+}
+
+ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ BYTE const symbol = DInfo.symbol;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+
+ DStatePtr->state = DInfo.newState + lowBits;
+ return symbol;
+}
+
+/*! FSE_decodeSymbolFast() :
+ unsafe, only works if no symbol has a probability > 50% */
+ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ BYTE const symbol = DInfo.symbol;
+ size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
+
+ DStatePtr->state = DInfo.newState + lowBits;
+ return symbol;
+}
+
+ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr) { return DStatePtr->state == 0; }
+
+/* **************************************************************
+* Tuning parameters
+****************************************************************/
+/*!MEMORY_USAGE :
+* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+* Increasing memory usage improves compression ratio
+* Reduced memory usage can improve speed, due to cache effect
+* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
+#ifndef FSE_MAX_MEMORY_USAGE
+#define FSE_MAX_MEMORY_USAGE 14
+#endif
+#ifndef FSE_DEFAULT_MEMORY_USAGE
+#define FSE_DEFAULT_MEMORY_USAGE 13
+#endif
+
+/*!FSE_MAX_SYMBOL_VALUE :
+* Maximum symbol value authorized.
+* Required for proper stack allocation */
+#ifndef FSE_MAX_SYMBOL_VALUE
+#define FSE_MAX_SYMBOL_VALUE 255
+#endif
+
+/* **************************************************************
+* template functions type & suffix
+****************************************************************/
+#define FSE_FUNCTION_TYPE BYTE
+#define FSE_FUNCTION_EXTENSION
+#define FSE_DECODE_TYPE FSE_decode_t
+
+/* ***************************************************************
+* Constants
+*****************************************************************/
+#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE - 2)
+#define FSE_MAX_TABLESIZE (1U << FSE_MAX_TABLELOG)
+#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE - 1)
+#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE - 2)
+#define FSE_MIN_TABLELOG 5
+
+#define FSE_TABLELOG_ABSOLUTE_MAX 15
+#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
+#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
+#endif
+
+#define FSE_TABLESTEP(tableSize) ((tableSize >> 1) + (tableSize >> 3) + 3)
+
+#endif /* FSE_H */
diff --git a/lib/zstd/fse_decompress.c b/lib/zstd/fse_decompress.c
new file mode 100644
index 00000000..3b4522b4
--- /dev/null
+++ b/lib/zstd/fse_decompress.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
+/*
+ * FSE : Finite State Entropy decoder
+ * Copyright (C) 2013-2015, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* **************************************************************
+* Compiler specifics
+****************************************************************/
+#define FORCE_INLINE static __always_inline
+
+/* **************************************************************
+* Includes
+****************************************************************/
+#include "bitstream.h"
+#include "fse.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h> /* memcpy, memset */
+
+/* **************************************************************
+* Error Management
+****************************************************************/
+#define FSE_isError ERR_isError
+#define FSE_STATIC_ASSERT(c) \
+ { \
+ enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
+ } /* use only *after* variable declarations */
+
+/* check and forward error code */
+#define CHECK_F(f) \
+ { \
+ size_t const e = f; \
+ if (FSE_isError(e)) \
+ return e; \
+ }
+
+/* **************************************************************
+* Templates
+****************************************************************/
+/*
+ designed to be included
+ for type-specific functions (template emulation in C)
+ Objective is to write these functions only once, for improved maintenance
+*/
+
+/* safety checks */
+#ifndef FSE_FUNCTION_EXTENSION
+#error "FSE_FUNCTION_EXTENSION must be defined"
+#endif
+#ifndef FSE_FUNCTION_TYPE
+#error "FSE_FUNCTION_TYPE must be defined"
+#endif
+
+/* Function names */
+#define FSE_CAT(X, Y) X##Y
+#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
+#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
+
+/* Function templates */
+
+size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize)
+{
+ void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
+ FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr);
+ U16 *symbolNext = (U16 *)workspace;
+
+ U32 const maxSV1 = maxSymbolValue + 1;
+ U32 const tableSize = 1 << tableLog;
+ U32 highThreshold = tableSize - 1;
+
+ /* Sanity Checks */
+ if (workspaceSize < sizeof(U16) * (FSE_MAX_SYMBOL_VALUE + 1))
+ return ERROR(tableLog_tooLarge);
+ if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE)
+ return ERROR(maxSymbolValue_tooLarge);
+ if (tableLog > FSE_MAX_TABLELOG)
+ return ERROR(tableLog_tooLarge);
+
+ /* Init, lay down lowprob symbols */
+ {
+ FSE_DTableHeader DTableH;
+ DTableH.tableLog = (U16)tableLog;
+ DTableH.fastMode = 1;
+ {
+ S16 const largeLimit = (S16)(1 << (tableLog - 1));
+ U32 s;
+ for (s = 0; s < maxSV1; s++) {
+ if (normalizedCounter[s] == -1) {
+ tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
+ symbolNext[s] = 1;
+ } else {
+ if (normalizedCounter[s] >= largeLimit)
+ DTableH.fastMode = 0;
+ symbolNext[s] = normalizedCounter[s];
+ }
+ }
+ }
+ memcpy(dt, &DTableH, sizeof(DTableH));
+ }
+
+ /* Spread symbols */
+ {
+ U32 const tableMask = tableSize - 1;
+ U32 const step = FSE_TABLESTEP(tableSize);
+ U32 s, position = 0;
+ for (s = 0; s < maxSV1; s++) {
+ int i;
+ for (i = 0; i < normalizedCounter[s]; i++) {
+ tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
+ position = (position + step) & tableMask;
+ while (position > highThreshold)
+ position = (position + step) & tableMask; /* lowprob area */
+ }
+ }
+ if (position != 0)
+ return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+ }
+
+ /* Build Decoding table */
+ {
+ U32 u;
+ for (u = 0; u < tableSize; u++) {
+ FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
+ U16 nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState));
+ tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
+ }
+ }
+
+ return 0;
+}
+
+/*-*******************************************************
+* Decompression (Byte symbols)
+*********************************************************/
+size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue)
+{
+ void *ptr = dt;
+ FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
+ void *dPtr = dt + 1;
+ FSE_decode_t *const cell = (FSE_decode_t *)dPtr;
+
+ DTableH->tableLog = 0;
+ DTableH->fastMode = 0;
+
+ cell->newState = 0;
+ cell->symbol = symbolValue;
+ cell->nbBits = 0;
+
+ return 0;
+}
+
+size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits)
+{
+ void *ptr = dt;
+ FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
+ void *dPtr = dt + 1;
+ FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr;
+ const unsigned tableSize = 1 << nbBits;
+ const unsigned tableMask = tableSize - 1;
+ const unsigned maxSV1 = tableMask + 1;
+ unsigned s;
+
+ /* Sanity checks */
+ if (nbBits < 1)
+ return ERROR(GENERIC); /* min size */
+
+ /* Build Decoding Table */
+ DTableH->tableLog = (U16)nbBits;
+ DTableH->fastMode = 1;
+ for (s = 0; s < maxSV1; s++) {
+ dinfo[s].newState = 0;
+ dinfo[s].symbol = (BYTE)s;
+ dinfo[s].nbBits = (BYTE)nbBits;
+ }
+
+ return 0;
+}
+
+FORCE_INLINE size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt,
+ const unsigned fast)
+{
+ BYTE *const ostart = (BYTE *)dst;
+ BYTE *op = ostart;
+ BYTE *const omax = op + maxDstSize;
+ BYTE *const olimit = omax - 3;
+
+ BIT_DStream_t bitD;
+ FSE_DState_t state1;
+ FSE_DState_t state2;
+
+ /* Init */
+ CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
+
+ FSE_initDState(&state1, &bitD, dt);
+ FSE_initDState(&state2, &bitD, dt);
+
+#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
+
+ /* 4 symbols per loop */
+ for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) {
+ op[0] = FSE_GETSYMBOL(&state1);
+
+ if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+ BIT_reloadDStream(&bitD);
+
+ op[1] = FSE_GETSYMBOL(&state2);
+
+ if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+ {
+ if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) {
+ op += 2;
+ break;
+ }
+ }
+
+ op[2] = FSE_GETSYMBOL(&state1);
+
+ if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+ BIT_reloadDStream(&bitD);
+
+ op[3] = FSE_GETSYMBOL(&state2);
+ }
+
+ /* tail */
+ /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
+ while (1) {
+ if (op > (omax - 2))
+ return ERROR(dstSize_tooSmall);
+ *op++ = FSE_GETSYMBOL(&state1);
+ if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
+ *op++ = FSE_GETSYMBOL(&state2);
+ break;
+ }
+
+ if (op > (omax - 2))
+ return ERROR(dstSize_tooSmall);
+ *op++ = FSE_GETSYMBOL(&state2);
+ if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
+ *op++ = FSE_GETSYMBOL(&state1);
+ break;
+ }
+ }
+
+ return op - ostart;
+}
+
+size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt)
+{
+ const void *ptr = dt;
+ const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr;
+ const U32 fastMode = DTableH->fastMode;
+
+ /* select fast mode (static) */
+ if (fastMode)
+ return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
+ return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
+}
+
+size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize)
+{
+ const BYTE *const istart = (const BYTE *)cSrc;
+ const BYTE *ip = istart;
+ unsigned tableLog;
+ unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
+ size_t NCountLength;
+
+ FSE_DTable *dt;
+ short *counting;
+ size_t spaceUsed32 = 0;
+
+ FSE_STATIC_ASSERT(sizeof(FSE_DTable) == sizeof(U32));
+
+ dt = (FSE_DTable *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += FSE_DTABLE_SIZE_U32(maxLog);
+ counting = (short *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += ALIGN(sizeof(short) * (FSE_MAX_SYMBOL_VALUE + 1), sizeof(U32)) >> 2;
+
+ if ((spaceUsed32 << 2) > workspaceSize)
+ return ERROR(tableLog_tooLarge);
+ workspace = (U32 *)workspace + spaceUsed32;
+ workspaceSize -= (spaceUsed32 << 2);
+
+ /* normal FSE decoding mode */
+ NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
+ if (FSE_isError(NCountLength))
+ return NCountLength;
+ // if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining
+ // case : NCountLength==cSrcSize */
+ if (tableLog > maxLog)
+ return ERROR(tableLog_tooLarge);
+ ip += NCountLength;
+ cSrcSize -= NCountLength;
+
+ CHECK_F(FSE_buildDTable_wksp(dt, counting, maxSymbolValue, tableLog, workspace, workspaceSize));
+
+ return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, dt); /* always return, even if it is an error code */
+}
diff --git a/lib/zstd/huf.h b/lib/zstd/huf.h
new file mode 100644
index 00000000..01630f56
--- /dev/null
+++ b/lib/zstd/huf.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
+/*
+ * Huffman coder, part of New Generation Entropy library
+ * header file
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef HUF_H_298734234
+#define HUF_H_298734234
+
+/* *** Dependencies *** */
+#include <linux/types.h> /* size_t */
+
+/* *** Tool functions *** */
+#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
+size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
+
+/* Error Management */
+unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
+
+/* *** Advanced function *** */
+
+/** HUF_compress4X_wksp() :
+* Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */
+size_t HUF_compress4X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+ size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+/* *** Dependencies *** */
+#include "mem.h" /* U32 */
+
+/* *** Constants *** */
+#define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
+#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
+#define HUF_SYMBOLVALUE_MAX 255
+
+#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
+#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
+#error "HUF_TABLELOG_MAX is too large !"
+#endif
+
+/* ****************************************
+* Static allocation
+******************************************/
+/* HUF buffer bounds */
+#define HUF_CTABLEBOUND 129
+#define HUF_BLOCKBOUND(size) (size + (size >> 8) + 8) /* only true if incompressible pre-filtered with fast heuristic */
+#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* static allocation of HUF's Compression Table */
+#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
+ U32 name##hb[maxSymbolValue + 1]; \
+ void *name##hv = &(name##hb); \
+ HUF_CElt *name = (HUF_CElt *)(name##hv) /* no final ; */
+
+/* static allocation of HUF's DTable */
+typedef U32 HUF_DTable;
+#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << (maxTableLog)))
+#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = {((U32)((maxTableLog)-1) * 0x01000001)}
+#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = {((U32)(maxTableLog)*0x01000001)}
+
+/* The workspace must have alignment at least 4 and be at least this large */
+#define HUF_COMPRESS_WORKSPACE_SIZE (6 << 10)
+#define HUF_COMPRESS_WORKSPACE_SIZE_U32 (HUF_COMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
+/* The workspace must have alignment at least 4 and be at least this large */
+#define HUF_DECOMPRESS_WORKSPACE_SIZE (3 << 10)
+#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
+/* ****************************************
+* Advanced decompression functions
+******************************************/
+size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize); /**< decodes RLE and uncompressed */
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+ size_t workspaceSize); /**< considers RLE and uncompressed as errors */
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+ size_t workspaceSize); /**< single-symbol decoder */
+size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+ size_t workspaceSize); /**< double-symbols decoder */
+
+/* ****************************************
+* HUF detailed API
+******************************************/
+/*!
+HUF_compress() does the following:
+1. count symbol occurrence from source[] into table count[] using FSE_count()
+2. (optional) refine tableLog using HUF_optimalTableLog()
+3. build Huffman table from count using HUF_buildCTable()
+4. save Huffman table to memory buffer using HUF_writeCTable_wksp()
+5. encode the data stream using HUF_compress4X_usingCTable()
+
+The following API allows targeting specific sub-functions for advanced tasks.
+For example, it's possible to compress several blocks using the same 'CTable',
+or to save and regenerate 'CTable' using external methods.
+*/
+/* FSE_count() : find it within "fse.h" */
+unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
+size_t HUF_writeCTable_wksp(void *dst, size_t maxDstSize, const HUF_CElt *CTable, unsigned maxSymbolValue, unsigned huffLog, void *workspace, size_t workspaceSize);
+size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
+
+typedef enum {
+ HUF_repeat_none, /**< Cannot use the previous table */
+ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
+ 4}X_repeat */
+ HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
+} HUF_repeat;
+/** HUF_compress4X_repeat() :
+* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+* If it uses hufTable it does not modify hufTable or repeat.
+* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+* If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress4X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+ size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
+ int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+/** HUF_buildCTable_wksp() :
+ * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
+ * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
+ */
+size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize);
+
+/*! HUF_readStats() :
+ Read compact Huffman tree, saved by HUF_writeCTable().
+ `huffWeight` is destination buffer.
+ @return : size read from `src` , or an error Code .
+ Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
+size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize,
+ void *workspace, size_t workspaceSize);
+
+/** HUF_readCTable() :
+* Loading a CTable saved with HUF_writeCTable() */
+size_t HUF_readCTable_wksp(HUF_CElt *CTable, unsigned maxSymbolValue, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+
+/*
+HUF_decompress() does the following:
+1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
+2. build Huffman table from save, using HUF_readDTableXn()
+3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable
+*/
+
+/** HUF_selectDecoder() :
+* Tells which decoder is likely to decode faster,
+* based on a set of pre-determined metrics.
+* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
+U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize);
+
+size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+
+size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress4X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress4X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+
+/* single stream variants */
+
+size_t HUF_compress1X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+ size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
+/** HUF_compress1X_repeat() :
+* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+* If it uses hufTable it does not modify hufTable or repeat.
+* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+* If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress1X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+ size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
+ int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize);
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+ size_t workspaceSize); /**< single-symbol decoder */
+size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+ size_t workspaceSize); /**< double-symbols decoder */
+
+size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize,
+ const HUF_DTable *DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
+size_t HUF_decompress1X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress1X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+
+#endif /* HUF_H_298734234 */
diff --git a/lib/zstd/huf_decompress.c b/lib/zstd/huf_decompress.c
new file mode 100644
index 00000000..97145b06
--- /dev/null
+++ b/lib/zstd/huf_decompress.c
@@ -0,0 +1,930 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
+/*
+ * Huffman decoder, part of New Generation Entropy library
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* **************************************************************
+* Compiler specifics
+****************************************************************/
+#define FORCE_INLINE static __always_inline
+
+/* **************************************************************
+* Dependencies
+****************************************************************/
+#include "bitstream.h" /* BIT_* */
+#include "fse.h" /* header compression */
+#include "huf.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h> /* memcpy, memset */
+
+/* **************************************************************
+* Error Management
+****************************************************************/
+#define HUF_STATIC_ASSERT(c) \
+ { \
+ enum { HUF_static_assert = 1 / (int)(!!(c)) }; \
+ } /* use only *after* variable declarations */
+
+/*-***************************/
+/* generic DTableDesc */
+/*-***************************/
+
+typedef struct {
+ BYTE maxTableLog;
+ BYTE tableType;
+ BYTE tableLog;
+ BYTE reserved;
+} DTableDesc;
+
+static DTableDesc HUF_getDTableDesc(const HUF_DTable *table)
+{
+ DTableDesc dtd;
+ memcpy(&dtd, table, sizeof(dtd));
+ return dtd;
+}
+
+/*-***************************/
+/* single-symbol decoding */
+/*-***************************/
+
+typedef struct {
+ BYTE byte;
+ BYTE nbBits;
+} HUF_DEltX2; /* single-symbol decoding */
+
+size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+ U32 tableLog = 0;
+ U32 nbSymbols = 0;
+ size_t iSize;
+ void *const dtPtr = DTable + 1;
+ HUF_DEltX2 *const dt = (HUF_DEltX2 *)dtPtr;
+
+ U32 *rankVal;
+ BYTE *huffWeight;
+ size_t spaceUsed32 = 0;
+
+ rankVal = (U32 *)workspace + spaceUsed32;
+ spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
+ huffWeight = (BYTE *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
+
+ if ((spaceUsed32 << 2) > workspaceSize)
+ return ERROR(tableLog_tooLarge);
+ workspace = (U32 *)workspace + spaceUsed32;
+ workspaceSize -= (spaceUsed32 << 2);
+
+ HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
+ /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
+
+ iSize = HUF_readStats_wksp(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
+ if (HUF_isError(iSize))
+ return iSize;
+
+ /* Table header */
+ {
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (tableLog > (U32)(dtd.maxTableLog + 1))
+ return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
+ dtd.tableType = 0;
+ dtd.tableLog = (BYTE)tableLog;
+ memcpy(DTable, &dtd, sizeof(dtd));
+ }
+
+ /* Calculate starting value for each rank */
+ {
+ U32 n, nextRankStart = 0;
+ for (n = 1; n < tableLog + 1; n++) {
+ U32 const curr = nextRankStart;
+ nextRankStart += (rankVal[n] << (n - 1));
+ rankVal[n] = curr;
+ }
+ }
+
+ /* fill DTable */
+ {
+ U32 n;
+ for (n = 0; n < nbSymbols; n++) {
+ U32 const w = huffWeight[n];
+ U32 const length = (1 << w) >> 1;
+ U32 u;
+ HUF_DEltX2 D;
+ D.byte = (BYTE)n;
+ D.nbBits = (BYTE)(tableLog + 1 - w);
+ for (u = rankVal[w]; u < rankVal[w] + length; u++)
+ dt[u] = D;
+ rankVal[w] += length;
+ }
+ }
+
+ return iSize;
+}
+
+static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
+ BYTE const c = dt[val].byte;
+ BIT_skipBits(Dstream, dt[val].nbBits);
+ return c;
+}
+
+#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
+ if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
+ HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+
+#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
+ if (ZSTD_64bits()) \
+ HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+
+FORCE_INLINE size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog)
+{
+ BYTE *const pStart = p;
+
+ /* up to 4 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) {
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+
+ /* closer to the end */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+ /* no more data to retrieve from bitstream, hence no need to reload */
+ while (p < pEnd)
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+ return pEnd - pStart;
+}
+
+static size_t HUF_decompress1X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ BYTE *op = (BYTE *)dst;
+ BYTE *const oend = op + dstSize;
+ const void *dtPtr = DTable + 1;
+ const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
+ BIT_DStream_t bitD;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ {
+ size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+
+ HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
+
+ /* check */
+ if (!BIT_endOfDStream(&bitD))
+ return ERROR(corruption_detected);
+
+ return dstSize;
+}
+
+size_t HUF_decompress1X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 0)
+ return ERROR(GENERIC);
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ const BYTE *ip = (const BYTE *)cSrc;
+
+ size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
+ if (HUF_isError(hSize))
+ return hSize;
+ if (hSize >= cSrcSize)
+ return ERROR(srcSize_wrong);
+ ip += hSize;
+ cSrcSize -= hSize;
+
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
+}
+
+static size_t HUF_decompress4X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ /* Check */
+ if (cSrcSize < 10)
+ return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ {
+ const BYTE *const istart = (const BYTE *)cSrc;
+ BYTE *const ostart = (BYTE *)dst;
+ BYTE *const oend = ostart + dstSize;
+ const void *const dtPtr = DTable + 1;
+ const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = ZSTD_readLE16(istart);
+ size_t const length2 = ZSTD_readLE16(istart + 2);
+ size_t const length3 = ZSTD_readLE16(istart + 4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE *const istart1 = istart + 6; /* jumpTable */
+ const BYTE *const istart2 = istart1 + length1;
+ const BYTE *const istart3 = istart2 + length2;
+ const BYTE *const istart4 = istart3 + length3;
+ const size_t segmentSize = (dstSize + 3) / 4;
+ BYTE *const opStart2 = ostart + segmentSize;
+ BYTE *const opStart3 = opStart2 + segmentSize;
+ BYTE *const opStart4 = opStart3 + segmentSize;
+ BYTE *op1 = ostart;
+ BYTE *op2 = opStart2;
+ BYTE *op3 = opStart3;
+ BYTE *op4 = opStart4;
+ U32 endSignal;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ if (length4 > cSrcSize)
+ return ERROR(corruption_detected); /* overflow */
+ {
+ size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) {
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ }
+
+ /* check corruption */
+ if (op1 > opStart2)
+ return ERROR(corruption_detected);
+ if (op2 > opStart3)
+ return ERROR(corruption_detected);
+ if (op3 > opStart4)
+ return ERROR(corruption_detected);
+ /* note : op4 supposed already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endSignal)
+ return ERROR(corruption_detected);
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+size_t HUF_decompress4X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 0)
+ return ERROR(GENERIC);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ const BYTE *ip = (const BYTE *)cSrc;
+
+ size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
+ if (HUF_isError(hSize))
+ return hSize;
+ if (hSize >= cSrcSize)
+ return ERROR(srcSize_wrong);
+ ip += hSize;
+ cSrcSize -= hSize;
+
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
+}
+
+/* *************************/
+/* double-symbols decoding */
+/* *************************/
+typedef struct {
+ U16 sequence;
+ BYTE nbBits;
+ BYTE length;
+} HUF_DEltX4; /* double-symbols decoding */
+
+typedef struct {
+ BYTE symbol;
+ BYTE weight;
+} sortedSymbol_t;
+
+/* HUF_fillDTableX4Level2() :
+ * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
+static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, const U32 *rankValOrigin, const int minWeight,
+ const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, U32 nbBitsBaseline, U16 baseSeq)
+{
+ HUF_DEltX4 DElt;
+ U32 rankVal[HUF_TABLELOG_MAX + 1];
+
+ /* get pre-calculated rankVal */
+ memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+
+ /* fill skipped values */
+ if (minWeight > 1) {
+ U32 i, skipSize = rankVal[minWeight];
+ ZSTD_writeLE16(&(DElt.sequence), baseSeq);
+ DElt.nbBits = (BYTE)(consumed);
+ DElt.length = 1;
+ for (i = 0; i < skipSize; i++)
+ DTable[i] = DElt;
+ }
+
+ /* fill DTable */
+ {
+ U32 s;
+ for (s = 0; s < sortedListSize; s++) { /* note : sortedSymbols already skipped */
+ const U32 symbol = sortedSymbols[s].symbol;
+ const U32 weight = sortedSymbols[s].weight;
+ const U32 nbBits = nbBitsBaseline - weight;
+ const U32 length = 1 << (sizeLog - nbBits);
+ const U32 start = rankVal[weight];
+ U32 i = start;
+ const U32 end = start + length;
+
+ ZSTD_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
+ DElt.nbBits = (BYTE)(nbBits + consumed);
+ DElt.length = 2;
+ do {
+ DTable[i++] = DElt;
+ } while (i < end); /* since length >= 1 */
+
+ rankVal[weight] += length;
+ }
+ }
+}
+
+typedef U32 rankVal_t[HUF_TABLELOG_MAX][HUF_TABLELOG_MAX + 1];
+typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
+
+static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, const sortedSymbol_t *sortedList, const U32 sortedListSize, const U32 *rankStart,
+ rankVal_t rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline)
+{
+ U32 rankVal[HUF_TABLELOG_MAX + 1];
+ const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
+ const U32 minBits = nbBitsBaseline - maxWeight;
+ U32 s;
+
+ memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+
+ /* fill DTable */
+ for (s = 0; s < sortedListSize; s++) {
+ const U16 symbol = sortedList[s].symbol;
+ const U32 weight = sortedList[s].weight;
+ const U32 nbBits = nbBitsBaseline - weight;
+ const U32 start = rankVal[weight];
+ const U32 length = 1 << (targetLog - nbBits);
+
+ if (targetLog - nbBits >= minBits) { /* enough room for a second symbol */
+ U32 sortedRank;
+ int minWeight = nbBits + scaleLog;
+ if (minWeight < 1)
+ minWeight = 1;
+ sortedRank = rankStart[minWeight];
+ HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList + sortedRank,
+ sortedListSize - sortedRank, nbBitsBaseline, symbol);
+ } else {
+ HUF_DEltX4 DElt;
+ ZSTD_writeLE16(&(DElt.sequence), symbol);
+ DElt.nbBits = (BYTE)(nbBits);
+ DElt.length = 1;
+ {
+ U32 const end = start + length;
+ U32 u;
+ for (u = start; u < end; u++)
+ DTable[u] = DElt;
+ }
+ }
+ rankVal[weight] += length;
+ }
+}
+
+size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+ U32 tableLog, maxW, sizeOfSort, nbSymbols;
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ U32 const maxTableLog = dtd.maxTableLog;
+ size_t iSize;
+ void *dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */
+ HUF_DEltX4 *const dt = (HUF_DEltX4 *)dtPtr;
+ U32 *rankStart;
+
+ rankValCol_t *rankVal;
+ U32 *rankStats;
+ U32 *rankStart0;
+ sortedSymbol_t *sortedSymbol;
+ BYTE *weightList;
+ size_t spaceUsed32 = 0;
+
+ HUF_STATIC_ASSERT((sizeof(rankValCol_t) & 3) == 0);
+
+ rankVal = (rankValCol_t *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
+ rankStats = (U32 *)workspace + spaceUsed32;
+ spaceUsed32 += HUF_TABLELOG_MAX + 1;
+ rankStart0 = (U32 *)workspace + spaceUsed32;
+ spaceUsed32 += HUF_TABLELOG_MAX + 2;
+ sortedSymbol = (sortedSymbol_t *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
+ weightList = (BYTE *)((U32 *)workspace + spaceUsed32);
+ spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
+
+ if ((spaceUsed32 << 2) > workspaceSize)
+ return ERROR(tableLog_tooLarge);
+ workspace = (U32 *)workspace + spaceUsed32;
+ workspaceSize -= (spaceUsed32 << 2);
+
+ rankStart = rankStart0 + 1;
+ memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
+
+ HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
+ if (maxTableLog > HUF_TABLELOG_MAX)
+ return ERROR(tableLog_tooLarge);
+ /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
+
+ iSize = HUF_readStats_wksp(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
+ if (HUF_isError(iSize))
+ return iSize;
+
+ /* check result */
+ if (tableLog > maxTableLog)
+ return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
+
+ /* find maxWeight */
+ for (maxW = tableLog; rankStats[maxW] == 0; maxW--) {
+ } /* necessarily finds a solution before 0 */
+
+ /* Get start index of each weight */
+ {
+ U32 w, nextRankStart = 0;
+ for (w = 1; w < maxW + 1; w++) {
+ U32 curr = nextRankStart;
+ nextRankStart += rankStats[w];
+ rankStart[w] = curr;
+ }
+ rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
+ sizeOfSort = nextRankStart;
+ }
+
+ /* sort symbols by weight */
+ {
+ U32 s;
+ for (s = 0; s < nbSymbols; s++) {
+ U32 const w = weightList[s];
+ U32 const r = rankStart[w]++;
+ sortedSymbol[r].symbol = (BYTE)s;
+ sortedSymbol[r].weight = (BYTE)w;
+ }
+ rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
+ }
+
+ /* Build rankVal */
+ {
+ U32 *const rankVal0 = rankVal[0];
+ {
+ int const rescale = (maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */
+ U32 nextRankVal = 0;
+ U32 w;
+ for (w = 1; w < maxW + 1; w++) {
+ U32 curr = nextRankVal;
+ nextRankVal += rankStats[w] << (w + rescale);
+ rankVal0[w] = curr;
+ }
+ }
+ {
+ U32 const minBits = tableLog + 1 - maxW;
+ U32 consumed;
+ for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
+ U32 *const rankValPtr = rankVal[consumed];
+ U32 w;
+ for (w = 1; w < maxW + 1; w++) {
+ rankValPtr[w] = rankVal0[w] >> consumed;
+ }
+ }
+ }
+ }
+
+ HUF_fillDTableX4(dt, maxTableLog, sortedSymbol, sizeOfSort, rankStart0, rankVal, maxW, tableLog + 1);
+
+ dtd.tableLog = (BYTE)maxTableLog;
+ dtd.tableType = 1;
+ memcpy(DTable, &dtd, sizeof(dtd));
+ return iSize;
+}
+
+static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt + val, 2);
+ BIT_skipBits(DStream, dt[val].nbBits);
+ return dt[val].length;
+}
+
+static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt + val, 1);
+ if (dt[val].length == 1)
+ BIT_skipBits(DStream, dt[val].nbBits);
+ else {
+ if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8))
+ /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
+ DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8);
+ }
+ }
+ return 1;
+}
+
+#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
+ if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
+ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
+ if (ZSTD_64bits()) \
+ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+FORCE_INLINE size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog)
+{
+ BYTE *const pStart = p;
+
+ /* up to 8 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd - (sizeof(bitDPtr->bitContainer) - 1))) {
+ HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+ }
+
+ /* closer to end : up to 2 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd - 2))
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+
+ while (p <= pEnd - 2)
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+
+ if (p < pEnd)
+ p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
+
+ return p - pStart;
+}
+
+static size_t HUF_decompress1X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ BIT_DStream_t bitD;
+
+ /* Init */
+ {
+ size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+
+ /* decode */
+ {
+ BYTE *const ostart = (BYTE *)dst;
+ BYTE *const oend = ostart + dstSize;
+ const void *const dtPtr = DTable + 1; /* force compiler to not use strict-aliasing */
+ const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
+ }
+
+ /* check */
+ if (!BIT_endOfDStream(&bitD))
+ return ERROR(corruption_detected);
+
+ /* decoded size */
+ return dstSize;
+}
+
+size_t HUF_decompress1X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 1)
+ return ERROR(GENERIC);
+ return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ const BYTE *ip = (const BYTE *)cSrc;
+
+ size_t const hSize = HUF_readDTableX4_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
+ if (HUF_isError(hSize))
+ return hSize;
+ if (hSize >= cSrcSize)
+ return ERROR(srcSize_wrong);
+ ip += hSize;
+ cSrcSize -= hSize;
+
+ return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
+}
+
+static size_t HUF_decompress4X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ if (cSrcSize < 10)
+ return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ {
+ const BYTE *const istart = (const BYTE *)cSrc;
+ BYTE *const ostart = (BYTE *)dst;
+ BYTE *const oend = ostart + dstSize;
+ const void *const dtPtr = DTable + 1;
+ const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = ZSTD_readLE16(istart);
+ size_t const length2 = ZSTD_readLE16(istart + 2);
+ size_t const length3 = ZSTD_readLE16(istart + 4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE *const istart1 = istart + 6; /* jumpTable */
+ const BYTE *const istart2 = istart1 + length1;
+ const BYTE *const istart3 = istart2 + length2;
+ const BYTE *const istart4 = istart3 + length3;
+ size_t const segmentSize = (dstSize + 3) / 4;
+ BYTE *const opStart2 = ostart + segmentSize;
+ BYTE *const opStart3 = opStart2 + segmentSize;
+ BYTE *const opStart4 = opStart3 + segmentSize;
+ BYTE *op1 = ostart;
+ BYTE *op2 = opStart2;
+ BYTE *op3 = opStart3;
+ BYTE *op4 = opStart4;
+ U32 endSignal;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ if (length4 > cSrcSize)
+ return ERROR(corruption_detected); /* overflow */
+ {
+ size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+ {
+ size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
+ if (HUF_isError(errorCode))
+ return errorCode;
+ }
+
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ for (; (endSignal == BIT_DStream_unfinished) & (op4 < (oend - (sizeof(bitD4.bitContainer) - 1)));) {
+ HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
+
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ }
+
+ /* check corruption */
+ if (op1 > opStart2)
+ return ERROR(corruption_detected);
+ if (op2 > opStart3)
+ return ERROR(corruption_detected);
+ if (op3 > opStart4)
+ return ERROR(corruption_detected);
+ /* note : op4 already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ {
+ U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck)
+ return ERROR(corruption_detected);
+ }
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+size_t HUF_decompress4X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 1)
+ return ERROR(GENERIC);
+ return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ const BYTE *ip = (const BYTE *)cSrc;
+
+ size_t hSize = HUF_readDTableX4_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
+ if (HUF_isError(hSize))
+ return hSize;
+ if (hSize >= cSrcSize)
+ return ERROR(srcSize_wrong);
+ ip += hSize;
+ cSrcSize -= hSize;
+
+ return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
+}
+
+/* ********************************/
+/* Generic decompression selector */
+/* ********************************/
+
+size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
+ : HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
+ : HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+}
+
+typedef struct {
+ U32 tableTime;
+ U32 decode256Time;
+} algo_time_t;
+static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = {
+ /* single, double, quad */
+ {{0, 0}, {1, 1}, {2, 2}}, /* Q==0 : impossible */
+ {{0, 0}, {1, 1}, {2, 2}}, /* Q==1 : impossible */
+ {{38, 130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
+ {{448, 128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
+ {{556, 128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
+ {{714, 128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
+ {{883, 128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
+ {{897, 128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
+ {{926, 128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
+ {{947, 128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
+ {{1107, 128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
+ {{1177, 128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
+ {{1242, 128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
+ {{1349, 128}, {2644, 106}, {5260, 106}}, /* Q ==13 : 81-87% */
+ {{1455, 128}, {2422, 124}, {4174, 124}}, /* Q ==14 : 87-93% */
+ {{722, 128}, {1891, 145}, {1936, 146}}, /* Q ==15 : 93-99% */
+};
+
+/** HUF_selectDecoder() :
+* Tells which decoder is likely to decode faster,
+* based on a set of pre-determined metrics.
+* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
+U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize)
+{
+ /* decoder timing evaluation */
+ U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
+ U32 const D256 = (U32)(dstSize >> 8);
+ U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
+ U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
+ DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
+
+ return DTime1 < DTime0;
+}
+
+typedef size_t (*decompressionAlgo)(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize);
+
+size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ /* validation checks */
+ if (dstSize == 0)
+ return ERROR(dstSize_tooSmall);
+ if (cSrcSize > dstSize)
+ return ERROR(corruption_detected); /* invalid */
+ if (cSrcSize == dstSize) {
+ memcpy(dst, cSrc, dstSize);
+ return dstSize;
+ } /* not compressed */
+ if (cSrcSize == 1) {
+ memset(dst, *(const BYTE *)cSrc, dstSize);
+ return dstSize;
+ } /* RLE */
+
+ {
+ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+ return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+ : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+ }
+}
+
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ /* validation checks */
+ if (dstSize == 0)
+ return ERROR(dstSize_tooSmall);
+ if ((cSrcSize >= dstSize) || (cSrcSize <= 1))
+ return ERROR(corruption_detected); /* invalid */
+
+ {
+ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+ return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+ : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+ }
+}
+
+size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+ /* validation checks */
+ if (dstSize == 0)
+ return ERROR(dstSize_tooSmall);
+ if (cSrcSize > dstSize)
+ return ERROR(corruption_detected); /* invalid */
+ if (cSrcSize == dstSize) {
+ memcpy(dst, cSrc, dstSize);
+ return dstSize;
+ } /* not compressed */
+ if (cSrcSize == 1) {
+ memset(dst, *(const BYTE *)cSrc, dstSize);
+ return dstSize;
+ } /* RLE */
+
+ {
+ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+ return algoNb ? HUF_decompress1X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+ : HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+ }
+}
diff --git a/lib/zstd/mem.h b/lib/zstd/mem.h
new file mode 100644
index 00000000..7225b397
--- /dev/null
+++ b/lib/zstd/mem.h
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+#ifndef MEM_H_MODULE
+#define MEM_H_MODULE
+
+/*-****************************************
+* Dependencies
+******************************************/
+#include <asm/unaligned.h>
+#include <compiler.h>
+#include <linux/string.h> /* memcpy */
+#include <linux/types.h> /* size_t, ptrdiff_t */
+
+/*-****************************************
+* Compiler specifics
+******************************************/
+#define ZSTD_STATIC static __inline __attribute__((unused))
+
+/*-**************************************************************
+* Basic Types
+*****************************************************************/
+typedef uint8_t BYTE;
+typedef uint16_t U16;
+typedef int16_t S16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+typedef int64_t S64;
+typedef ptrdiff_t iPtrDiff;
+typedef uintptr_t uPtrDiff;
+
+/*-**************************************************************
+* Memory I/O
+*****************************************************************/
+ZSTD_STATIC unsigned ZSTD_32bits(void) { return sizeof(size_t) == 4; }
+ZSTD_STATIC unsigned ZSTD_64bits(void) { return sizeof(size_t) == 8; }
+
+#if defined(__LITTLE_ENDIAN)
+#define ZSTD_LITTLE_ENDIAN 1
+#else
+#define ZSTD_LITTLE_ENDIAN 0
+#endif
+
+ZSTD_STATIC unsigned ZSTD_isLittleEndian(void) { return ZSTD_LITTLE_ENDIAN; }
+
+ZSTD_STATIC U16 ZSTD_read16(const void *memPtr) { return get_unaligned((const U16 *)memPtr); }
+
+ZSTD_STATIC U32 ZSTD_read32(const void *memPtr) { return get_unaligned((const U32 *)memPtr); }
+
+ZSTD_STATIC U64 ZSTD_read64(const void *memPtr) { return get_unaligned((const U64 *)memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readST(const void *memPtr) { return get_unaligned((const size_t *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write16(void *memPtr, U16 value) { put_unaligned(value, (U16 *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write32(void *memPtr, U32 value) { put_unaligned(value, (U32 *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write64(void *memPtr, U64 value) { put_unaligned(value, (U64 *)memPtr); }
+
+/*=== Little endian r/w ===*/
+
+ZSTD_STATIC U16 ZSTD_readLE16(const void *memPtr) { return get_unaligned_le16(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE16(void *memPtr, U16 val) { put_unaligned_le16(val, memPtr); }
+
+ZSTD_STATIC U32 ZSTD_readLE24(const void *memPtr) { return ZSTD_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); }
+
+ZSTD_STATIC void ZSTD_writeLE24(void *memPtr, U32 val)
+{
+ ZSTD_writeLE16(memPtr, (U16)val);
+ ((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
+}
+
+ZSTD_STATIC U32 ZSTD_readLE32(const void *memPtr) { return get_unaligned_le32(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE32(void *memPtr, U32 val32) { put_unaligned_le32(val32, memPtr); }
+
+ZSTD_STATIC U64 ZSTD_readLE64(const void *memPtr) { return get_unaligned_le64(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE64(void *memPtr, U64 val64) { put_unaligned_le64(val64, memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readLEST(const void *memPtr)
+{
+ if (ZSTD_32bits())
+ return (size_t)ZSTD_readLE32(memPtr);
+ else
+ return (size_t)ZSTD_readLE64(memPtr);
+}
+
+ZSTD_STATIC void ZSTD_writeLEST(void *memPtr, size_t val)
+{
+ if (ZSTD_32bits())
+ ZSTD_writeLE32(memPtr, (U32)val);
+ else
+ ZSTD_writeLE64(memPtr, (U64)val);
+}
+
+/*=== Big endian r/w ===*/
+
+ZSTD_STATIC U32 ZSTD_readBE32(const void *memPtr) { return get_unaligned_be32(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeBE32(void *memPtr, U32 val32) { put_unaligned_be32(val32, memPtr); }
+
+ZSTD_STATIC U64 ZSTD_readBE64(const void *memPtr) { return get_unaligned_be64(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeBE64(void *memPtr, U64 val64) { put_unaligned_be64(val64, memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readBEST(const void *memPtr)
+{
+ if (ZSTD_32bits())
+ return (size_t)ZSTD_readBE32(memPtr);
+ else
+ return (size_t)ZSTD_readBE64(memPtr);
+}
+
+ZSTD_STATIC void ZSTD_writeBEST(void *memPtr, size_t val)
+{
+ if (ZSTD_32bits())
+ ZSTD_writeBE32(memPtr, (U32)val);
+ else
+ ZSTD_writeBE64(memPtr, (U64)val);
+}
+
+/* function safe only for comparisons */
+ZSTD_STATIC U32 ZSTD_readMINMATCH(const void *memPtr, U32 length)
+{
+ switch (length) {
+ default:
+ case 4: return ZSTD_read32(memPtr);
+ case 3:
+ if (ZSTD_isLittleEndian())
+ return ZSTD_read32(memPtr) << 8;
+ else
+ return ZSTD_read32(memPtr) >> 8;
+ }
+}
+
+#endif /* MEM_H_MODULE */
diff --git a/lib/zstd/zstd_common.c b/lib/zstd/zstd_common.c
new file mode 100644
index 00000000..9a217e15
--- /dev/null
+++ b/lib/zstd/zstd_common.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear)
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+/*-*************************************
+* Dependencies
+***************************************/
+#include "error_private.h"
+#include "zstd_internal.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */
+#include <linux/kernel.h>
+
+/*=**************************************************************
+* Custom allocator
+****************************************************************/
+
+#define stack_push(stack, size) \
+ ({ \
+ void *const ptr = ZSTD_PTR_ALIGN((stack)->ptr); \
+ (stack)->ptr = (char *)ptr + (size); \
+ (stack)->ptr <= (stack)->end ? ptr : NULL; \
+ })
+
+ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize)
+{
+ ZSTD_customMem stackMem = {ZSTD_stackAlloc, ZSTD_stackFree, workspace};
+ ZSTD_stack *stack = (ZSTD_stack *)workspace;
+ /* Verify preconditions */
+ if (!workspace || workspaceSize < sizeof(ZSTD_stack) || workspace != ZSTD_PTR_ALIGN(workspace)) {
+ ZSTD_customMem error = {NULL, NULL, NULL};
+ return error;
+ }
+ /* Initialize the stack */
+ stack->ptr = workspace;
+ stack->end = (char *)workspace + workspaceSize;
+ stack_push(stack, sizeof(ZSTD_stack));
+ return stackMem;
+}
+
+void *ZSTD_stackAllocAll(void *opaque, size_t *size)
+{
+ ZSTD_stack *stack = (ZSTD_stack *)opaque;
+ *size = (BYTE const *)stack->end - (BYTE *)ZSTD_PTR_ALIGN(stack->ptr);
+ return stack_push(stack, *size);
+}
+
+void *ZSTD_stackAlloc(void *opaque, size_t size)
+{
+ ZSTD_stack *stack = (ZSTD_stack *)opaque;
+ return stack_push(stack, size);
+}
+void ZSTD_stackFree(void *opaque, void *address)
+{
+ (void)opaque;
+ (void)address;
+}
+
+void *ZSTD_malloc(size_t size, ZSTD_customMem customMem) { return customMem.customAlloc(customMem.opaque, size); }
+
+void ZSTD_free(void *ptr, ZSTD_customMem customMem)
+{
+ if (ptr != NULL)
+ customMem.customFree(customMem.opaque, ptr);
+}
diff --git a/lib/zstd/zstd_internal.h b/lib/zstd/zstd_internal.h
new file mode 100644
index 00000000..551340c8
--- /dev/null
+++ b/lib/zstd/zstd_internal.h
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+#ifndef ZSTD_CCOMMON_H_MODULE
+#define ZSTD_CCOMMON_H_MODULE
+
+/*-*******************************************************
+* Compiler specifics
+*********************************************************/
+#define FORCE_INLINE static __always_inline
+#define FORCE_NOINLINE static noinline
+
+/*-*************************************
+* Dependencies
+***************************************/
+#include "error_private.h"
+#include "mem.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/xxhash.h>
+#include <linux/zstd.h>
+
+/*-*************************************
+* shared macros
+***************************************/
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define CHECK_F(f) \
+ { \
+ size_t const errcod = f; \
+ if (ERR_isError(errcod)) \
+ return errcod; \
+ } /* check and Forward error code */
+#define CHECK_E(f, e) \
+ { \
+ size_t const errcod = f; \
+ if (ERR_isError(errcod)) \
+ return ERROR(e); \
+ } /* check and send Error code */
+#define ZSTD_STATIC_ASSERT(c) \
+ { \
+ enum { ZSTD_static_assert = 1 / (int)(!!(c)) }; \
+ }
+
+/*-*************************************
+* Common constants
+***************************************/
+#define ZSTD_OPT_NUM (1 << 12)
+#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */
+
+#define ZSTD_REP_NUM 3 /* number of repcodes */
+#define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */
+#define ZSTD_REP_MOVE (ZSTD_REP_NUM - 1)
+#define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM)
+static const U32 repStartValue[ZSTD_REP_NUM] = {1, 4, 8};
+
+#define KB *(1 << 10)
+#define MB *(1 << 20)
+#define GB *(1U << 30)
+
+#define BIT7 128
+#define BIT6 64
+#define BIT5 32
+#define BIT4 16
+#define BIT1 2
+#define BIT0 1
+
+#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
+static const size_t ZSTD_fcs_fieldSize[4] = {0, 2, 4, 8};
+static const size_t ZSTD_did_fieldSize[4] = {0, 1, 2, 4};
+
+#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
+static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
+typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
+
+#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
+#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
+
+#define HufLog 12
+typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
+
+#define LONGNBSEQ 0x7F00
+
+#define MINMATCH 3
+#define EQUAL_READ32 4
+
+#define Litbits 8
+#define MaxLit ((1 << Litbits) - 1)
+#define MaxML 52
+#define MaxLL 35
+#define MaxOff 28
+#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
+#define MLFSELog 9
+#define LLFSELog 9
+#define OffFSELog 8
+
+static const U32 LL_bits[MaxLL + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+static const S16 LL_defaultNorm[MaxLL + 1] = {4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};
+#define LL_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
+
+static const U32 ML_bits[MaxML + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+static const S16 ML_defaultNorm[MaxML + 1] = {1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1};
+#define ML_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
+
+static const S16 OF_defaultNorm[MaxOff + 1] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};
+#define OF_DEFAULTNORMLOG 5 /* for static allocation */
+static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
+
+/*-*******************************************
+* Shared functions to include for inlining
+*********************************************/
+ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) {
+ memcpy(dst, src, 8);
+}
+/*! ZSTD_wildcopy() :
+* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
+#define WILDCOPY_OVERLENGTH 8
+ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length)
+{
+ const BYTE* ip = (const BYTE*)src;
+ BYTE* op = (BYTE*)dst;
+ BYTE* const oend = op + length;
+ /* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388.
+ * Avoid the bad case where the loop only runs once by handling the
+ * special case separately. This doesn't trigger the bug because it
+ * doesn't involve pointer/integer overflow.
+ */
+ if (length <= 8)
+ return ZSTD_copy8(dst, src);
+ do {
+ ZSTD_copy8(op, ip);
+ op += 8;
+ ip += 8;
+ } while (op < oend);
+}
+
+/*-*******************************************
+* Private interfaces
+*********************************************/
+typedef struct ZSTD_stats_s ZSTD_stats_t;
+
+typedef struct {
+ U32 off;
+ U32 len;
+} ZSTD_match_t;
+
+typedef struct {
+ U32 price;
+ U32 off;
+ U32 mlen;
+ U32 litlen;
+ U32 rep[ZSTD_REP_NUM];
+} ZSTD_optimal_t;
+
+typedef struct seqDef_s {
+ U32 offset;
+ U16 litLength;
+ U16 matchLength;
+} seqDef;
+
+typedef struct {
+ seqDef *sequencesStart;
+ seqDef *sequences;
+ BYTE *litStart;
+ BYTE *lit;
+ BYTE *llCode;
+ BYTE *mlCode;
+ BYTE *ofCode;
+ U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
+ U32 longLengthPos;
+ /* opt */
+ ZSTD_optimal_t *priceTable;
+ ZSTD_match_t *matchTable;
+ U32 *matchLengthFreq;
+ U32 *litLengthFreq;
+ U32 *litFreq;
+ U32 *offCodeFreq;
+ U32 matchLengthSum;
+ U32 matchSum;
+ U32 litLengthSum;
+ U32 litSum;
+ U32 offCodeSum;
+ U32 log2matchLengthSum;
+ U32 log2matchSum;
+ U32 log2litLengthSum;
+ U32 log2litSum;
+ U32 log2offCodeSum;
+ U32 factor;
+ U32 staticPrices;
+ U32 cachedPrice;
+ U32 cachedLitLength;
+ const BYTE *cachedLiterals;
+} seqStore_t;
+
+const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx);
+void ZSTD_seqToCodes(const seqStore_t *seqStorePtr);
+int ZSTD_isSkipFrame(ZSTD_DCtx *dctx);
+
+/*= Custom memory allocation functions */
+typedef void *(*ZSTD_allocFunction)(void *opaque, size_t size);
+typedef void (*ZSTD_freeFunction)(void *opaque, void *address);
+typedef struct {
+ ZSTD_allocFunction customAlloc;
+ ZSTD_freeFunction customFree;
+ void *opaque;
+} ZSTD_customMem;
+
+void *ZSTD_malloc(size_t size, ZSTD_customMem customMem);
+void ZSTD_free(void *ptr, ZSTD_customMem customMem);
+
+/*====== stack allocation ======*/
+
+typedef struct {
+ void *ptr;
+ const void *end;
+} ZSTD_stack;
+
+#define ZSTD_ALIGN(x) ALIGN(x, sizeof(size_t))
+#define ZSTD_PTR_ALIGN(p) PTR_ALIGN(p, sizeof(size_t))
+
+ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize);
+
+void *ZSTD_stackAllocAll(void *opaque, size_t *size);
+void *ZSTD_stackAlloc(void *opaque, size_t size);
+void ZSTD_stackFree(void *opaque, void *address);
+
+/*====== common function ======*/
+
+ZSTD_STATIC U32 ZSTD_highbit32(U32 val) { return 31 - __builtin_clz(val); }
+
+/* hidden functions */
+
+/* ZSTD_invalidateRepCodes() :
+ * ensures next compression will not use repcodes from previous block.
+ * Note : only works with regular variant;
+ * do not use with extDict variant ! */
+void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx);
+
+size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx);
+size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx);
+size_t ZSTD_freeCDict(ZSTD_CDict *cdict);
+size_t ZSTD_freeDDict(ZSTD_DDict *cdict);
+size_t ZSTD_freeCStream(ZSTD_CStream *zcs);
+size_t ZSTD_freeDStream(ZSTD_DStream *zds);
+
+#endif /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd/zstd_opt.h b/lib/zstd/zstd_opt.h
new file mode 100644
index 00000000..af0aaf5b
--- /dev/null
+++ b/lib/zstd/zstd_opt.h
@@ -0,0 +1,1004 @@
+/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
+/**
+ * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ */
+
+/* Note : this file is intended to be included within zstd_compress.c */
+
+#ifndef ZSTD_OPT_H_91842398743
+#define ZSTD_OPT_H_91842398743
+
+#define ZSTD_LITFREQ_ADD 2
+#define ZSTD_FREQ_DIV 4
+#define ZSTD_MAX_PRICE (1 << 30)
+
+/*-*************************************
+* Price functions for optimal parser
+***************************************/
+FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t *ssPtr)
+{
+ ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum + 1);
+ ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum + 1);
+ ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum + 1);
+ ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum + 1);
+ ssPtr->factor = 1 + ((ssPtr->litSum >> 5) / ssPtr->litLengthSum) + ((ssPtr->litSum << 1) / (ssPtr->litSum + ssPtr->matchSum));
+}
+
+ZSTD_STATIC void ZSTD_rescaleFreqs(seqStore_t *ssPtr, const BYTE *src, size_t srcSize)
+{
+ unsigned u;
+
+ ssPtr->cachedLiterals = NULL;
+ ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
+ ssPtr->staticPrices = 0;
+
+ if (ssPtr->litLengthSum == 0) {
+ if (srcSize <= 1024)
+ ssPtr->staticPrices = 1;
+
+ for (u = 0; u <= MaxLit; u++)
+ ssPtr->litFreq[u] = 0;
+ for (u = 0; u < srcSize; u++)
+ ssPtr->litFreq[src[u]]++;
+
+ ssPtr->litSum = 0;
+ ssPtr->litLengthSum = MaxLL + 1;
+ ssPtr->matchLengthSum = MaxML + 1;
+ ssPtr->offCodeSum = (MaxOff + 1);
+ ssPtr->matchSum = (ZSTD_LITFREQ_ADD << Litbits);
+
+ for (u = 0; u <= MaxLit; u++) {
+ ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> ZSTD_FREQ_DIV);
+ ssPtr->litSum += ssPtr->litFreq[u];
+ }
+ for (u = 0; u <= MaxLL; u++)
+ ssPtr->litLengthFreq[u] = 1;
+ for (u = 0; u <= MaxML; u++)
+ ssPtr->matchLengthFreq[u] = 1;
+ for (u = 0; u <= MaxOff; u++)
+ ssPtr->offCodeFreq[u] = 1;
+ } else {
+ ssPtr->matchLengthSum = 0;
+ ssPtr->litLengthSum = 0;
+ ssPtr->offCodeSum = 0;
+ ssPtr->matchSum = 0;
+ ssPtr->litSum = 0;
+
+ for (u = 0; u <= MaxLit; u++) {
+ ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> (ZSTD_FREQ_DIV + 1));
+ ssPtr->litSum += ssPtr->litFreq[u];
+ }
+ for (u = 0; u <= MaxLL; u++) {
+ ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u] >> (ZSTD_FREQ_DIV + 1));
+ ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
+ }
+ for (u = 0; u <= MaxML; u++) {
+ ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u] >> ZSTD_FREQ_DIV);
+ ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
+ ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
+ }
+ ssPtr->matchSum *= ZSTD_LITFREQ_ADD;
+ for (u = 0; u <= MaxOff; u++) {
+ ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u] >> ZSTD_FREQ_DIV);
+ ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
+ }
+ }
+
+ ZSTD_setLog2Prices(ssPtr);
+}
+
+FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t *ssPtr, U32 litLength, const BYTE *literals)
+{
+ U32 price, u;
+
+ if (ssPtr->staticPrices)
+ return ZSTD_highbit32((U32)litLength + 1) + (litLength * 6);
+
+ if (litLength == 0)
+ return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0] + 1);
+
+ /* literals */
+ if (ssPtr->cachedLiterals == literals) {
+ U32 const additional = litLength - ssPtr->cachedLitLength;
+ const BYTE *literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength;
+ price = ssPtr->cachedPrice + additional * ssPtr->log2litSum;
+ for (u = 0; u < additional; u++)
+ price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]] + 1);
+ ssPtr->cachedPrice = price;
+ ssPtr->cachedLitLength = litLength;
+ } else {
+ price = litLength * ssPtr->log2litSum;
+ for (u = 0; u < litLength; u++)
+ price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]] + 1);
+
+ if (litLength >= 12) {
+ ssPtr->cachedLiterals = literals;
+ ssPtr->cachedPrice = price;
+ ssPtr->cachedLitLength = litLength;
+ }
+ }
+
+ /* literal Length */
+ {
+ const BYTE LL_deltaCode = 19;
+ const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+ price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode] + 1);
+ }
+
+ return price;
+}
+
+FORCE_INLINE U32 ZSTD_getPrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength, const int ultra)
+{
+ /* offset */
+ U32 price;
+ BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
+
+ if (seqStorePtr->staticPrices)
+ return ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit32((U32)matchLength + 1) + 16 + offCode;
+
+ price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode] + 1);
+ if (!ultra && offCode >= 20)
+ price += (offCode - 19) * 2;
+
+ /* match Length */
+ {
+ const BYTE ML_deltaCode = 36;
+ const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+ price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode] + 1);
+ }
+
+ return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
+}
+
+ZSTD_STATIC void ZSTD_updatePrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength)
+{
+ U32 u;
+
+ /* literals */
+ seqStorePtr->litSum += litLength * ZSTD_LITFREQ_ADD;
+ for (u = 0; u < litLength; u++)
+ seqStorePtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
+
+ /* literal Length */
+ {
+ const BYTE LL_deltaCode = 19;
+ const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+ seqStorePtr->litLengthFreq[llCode]++;
+ seqStorePtr->litLengthSum++;
+ }
+
+ /* match offset */
+ {
+ BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
+ seqStorePtr->offCodeSum++;
+ seqStorePtr->offCodeFreq[offCode]++;
+ }
+
+ /* match Length */
+ {
+ const BYTE ML_deltaCode = 36;
+ const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+ seqStorePtr->matchLengthFreq[mlCode]++;
+ seqStorePtr->matchLengthSum++;
+ }
+
+ ZSTD_setLog2Prices(seqStorePtr);
+}
+
+#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
+ { \
+ while (last_pos < pos) { \
+ opt[last_pos + 1].price = ZSTD_MAX_PRICE; \
+ last_pos++; \
+ } \
+ opt[pos].mlen = mlen_; \
+ opt[pos].off = offset_; \
+ opt[pos].litlen = litlen_; \
+ opt[pos].price = price_; \
+ }
+
+/* Update hashTable3 up to ip (excluded)
+ Assumption : always within prefix (i.e. not within extDict) */
+FORCE_INLINE
+U32 ZSTD_insertAndFindFirstIndexHash3(ZSTD_CCtx *zc, const BYTE *ip)
+{
+ U32 *const hashTable3 = zc->hashTable3;
+ U32 const hashLog3 = zc->hashLog3;
+ const BYTE *const base = zc->base;
+ U32 idx = zc->nextToUpdate3;
+ const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
+ const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
+
+ while (idx < target) {
+ hashTable3[ZSTD_hash3Ptr(base + idx, hashLog3)] = idx;
+ idx++;
+ }
+
+ return hashTable3[hash3];
+}
+
+/*-*************************************
+* Binary Tree search
+***************************************/
+static U32 ZSTD_insertBtAndGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, U32 nbCompares, const U32 mls, U32 extDict,
+ ZSTD_match_t *matches, const U32 minMatchLen)
+{
+ const BYTE *const base = zc->base;
+ const U32 curr = (U32)(ip - base);
+ const U32 hashLog = zc->params.cParams.hashLog;
+ const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32 *const hashTable = zc->hashTable;
+ U32 matchIndex = hashTable[h];
+ U32 *const bt = zc->chainTable;
+ const U32 btLog = zc->params.cParams.chainLog - 1;
+ const U32 btMask = (1U << btLog) - 1;
+ size_t commonLengthSmaller = 0, commonLengthLarger = 0;
+ const BYTE *const dictBase = zc->dictBase;
+ const U32 dictLimit = zc->dictLimit;
+ const BYTE *const dictEnd = dictBase + dictLimit;
+ const BYTE *const prefixStart = base + dictLimit;
+ const U32 btLow = btMask >= curr ? 0 : curr - btMask;
+ const U32 windowLow = zc->lowLimit;
+ U32 *smallerPtr = bt + 2 * (curr & btMask);
+ U32 *largerPtr = bt + 2 * (curr & btMask) + 1;
+ U32 matchEndIdx = curr + 8;
+ U32 dummy32; /* to be nullified at the end */
+ U32 mnum = 0;
+
+ const U32 minMatch = (mls == 3) ? 3 : 4;
+ size_t bestLength = minMatchLen - 1;
+
+ if (minMatch == 3) { /* HC3 match finder */
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(zc, ip);
+ if (matchIndex3 > windowLow && (curr - matchIndex3 < (1 << 18))) {
+ const BYTE *match;
+ size_t currMl = 0;
+ if ((!extDict) || matchIndex3 >= dictLimit) {
+ match = base + matchIndex3;
+ if (match[bestLength] == ip[bestLength])
+ currMl = ZSTD_count(ip, match, iLimit);
+ } else {
+ match = dictBase + matchIndex3;
+ if (ZSTD_readMINMATCH(match, MINMATCH) ==
+ ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
+ currMl = ZSTD_count_2segments(ip + MINMATCH, match + MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
+ }
+
+ /* save best solution */
+ if (currMl > bestLength) {
+ bestLength = currMl;
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex3;
+ matches[mnum].len = (U32)currMl;
+ mnum++;
+ if (currMl > ZSTD_OPT_NUM)
+ goto update;
+ if (ip + currMl == iLimit)
+ goto update; /* best possible, and avoid read overflow*/
+ }
+ }
+ }
+
+ hashTable[h] = curr; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32 *nextPtr = bt + 2 * (matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE *match;
+
+ if ((!extDict) || (matchIndex + matchLength >= dictLimit)) {
+ match = base + matchIndex;
+ if (match[matchLength] == ip[matchLength]) {
+ matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iLimit) + 1;
+ }
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iLimit, dictEnd, prefixStart);
+ if (matchIndex + matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ }
+
+ if (matchLength > bestLength) {
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ bestLength = matchLength;
+ matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex;
+ matches[mnum].len = (U32)matchLength;
+ mnum++;
+ if (matchLength > ZSTD_OPT_NUM)
+ break;
+ if (ip + matchLength == iLimit) /* equal : no way to know if inf or sup */
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+
+ if (match[matchLength] < ip[matchLength]) {
+ /* match is smaller than curr */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) {
+ smallerPtr = &dummy32;
+ break;
+ } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to curr) */
+ } else {
+ /* match is larger than curr */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) {
+ largerPtr = &dummy32;
+ break;
+ } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ }
+ }
+
+ *smallerPtr = *largerPtr = 0;
+
+update:
+ zc->nextToUpdate = (matchEndIdx > curr + 8) ? matchEndIdx - 8 : curr + 1;
+ return mnum;
+}
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches,
+ const U32 minMatchLen)
+{
+ if (ip < zc->base + zc->nextToUpdate)
+ return 0; /* skipped area */
+ ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
+}
+
+static U32 ZSTD_BtGetAllMatches_selectMLS(ZSTD_CCtx *zc, /* Index table will be updated */
+ const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
+ ZSTD_match_t *matches, const U32 minMatchLen)
+{
+ switch (matchLengthSearch) {
+ case 3: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+ default:
+ case 4: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+ case 5: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+ case 7:
+ case 6: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+ }
+}
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls,
+ ZSTD_match_t *matches, const U32 minMatchLen)
+{
+ if (ip < zc->base + zc->nextToUpdate)
+ return 0; /* skipped area */
+ ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
+ return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
+}
+
+static U32 ZSTD_BtGetAllMatches_selectMLS_extDict(ZSTD_CCtx *zc, /* Index table will be updated */
+ const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
+ ZSTD_match_t *matches, const U32 minMatchLen)
+{
+ switch (matchLengthSearch) {
+ case 3: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+ default:
+ case 4: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+ case 5: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+ case 7:
+ case 6: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+ }
+}
+
+/*-*******************************
+* Optimal parser
+*********************************/
+FORCE_INLINE
+void ZSTD_compressBlock_opt_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
+{
+ seqStore_t *seqStorePtr = &(ctx->seqStore);
+ const BYTE *const istart = (const BYTE *)src;
+ const BYTE *ip = istart;
+ const BYTE *anchor = istart;
+ const BYTE *const iend = istart + srcSize;
+ const BYTE *const ilimit = iend - 8;
+ const BYTE *const base = ctx->base;
+ const BYTE *const prefixStart = base + ctx->dictLimit;
+
+ const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
+ const U32 sufficient_len = ctx->params.cParams.targetLength;
+ const U32 mls = ctx->params.cParams.searchLength;
+ const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
+
+ ZSTD_optimal_t *opt = seqStorePtr->priceTable;
+ ZSTD_match_t *matches = seqStorePtr->matchTable;
+ const BYTE *inr;
+ U32 offset, rep[ZSTD_REP_NUM];
+
+ /* init */
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
+ ip += (ip == prefixStart);
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ rep[i] = ctx->rep[i];
+ }
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ U32 cur, match_num, last_pos, litlen, price;
+ U32 u, mlen, best_mlen, best_off, litLength;
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
+ last_pos = 0;
+ litlen = (U32)(ip - anchor);
+
+ /* check repCode */
+ {
+ U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
+ for (i = (ip == anchor); i < last_i; i++) {
+ const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+ if ((repCur > 0) && (repCur < (S32)(ip - prefixStart)) &&
+ (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
+ mlen = (U32)ZSTD_count(ip + minMatch, ip + minMatch - repCur, iend) + minMatch;
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen;
+ best_off = i;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+ best_off = i - (ip == anchor);
+ do {
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+ mlen--;
+ } while (mlen >= minMatch);
+ }
+ }
+ }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
+
+ if (!last_pos && !match_num) {
+ ip++;
+ continue;
+ }
+
+ if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num - 1].len;
+ best_off = matches[match_num - 1].off;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = 0 */
+ best_mlen = (last_pos) ? last_pos : minMatch;
+ for (u = 0; u < match_num; u++) {
+ mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+ best_mlen = matches[u].len;
+ while (mlen <= best_mlen) {
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
+ mlen++;
+ }
+ }
+
+ if (last_pos < minMatch) {
+ ip++;
+ continue;
+ }
+
+ /* initialize opt[0] */
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ opt[0].rep[i] = rep[i];
+ }
+ opt[0].mlen = 1;
+ opt[0].litlen = litlen;
+
+ /* check further positions */
+ for (cur = 1; cur <= last_pos; cur++) {
+ inr = ip + cur;
+
+ if (opt[cur - 1].mlen == 1) {
+ litlen = opt[cur - 1].litlen + 1;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
+ } else
+ price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
+ } else {
+ litlen = 1;
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
+ }
+
+ if (cur > last_pos || price <= opt[cur].price)
+ SET_PRICE(cur, 1, 0, litlen, price);
+
+ if (cur == last_pos)
+ break;
+
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+ continue;
+
+ mlen = opt[cur].mlen;
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+ opt[cur].rep[2] = opt[cur - mlen].rep[1];
+ opt[cur].rep[1] = opt[cur - mlen].rep[0];
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+ } else {
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
+ opt[cur].rep[0] =
+ ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
+ }
+
+ best_mlen = minMatch;
+ {
+ U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+ for (i = (opt[cur].mlen != 1); i < last_i; i++) { /* check rep */
+ const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+ if ((repCur > 0) && (repCur < (S32)(inr - prefixStart)) &&
+ (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
+ mlen = (U32)ZSTD_count(inr + minMatch, inr + minMatch - repCur, iend) + minMatch;
+
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen;
+ best_off = i;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (opt[cur].mlen != 1);
+ if (mlen > best_mlen)
+ best_mlen = mlen;
+
+ do {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
+ best_off, mlen - MINMATCH, ultra);
+ } else
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
+ mlen--;
+ } while (mlen >= minMatch);
+ }
+ }
+ }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
+
+ if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num - 1].len;
+ best_off = matches[match_num - 1].off;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = cur */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+ best_mlen = matches[u].len;
+
+ while (mlen <= best_mlen) {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen)
+ price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
+ matches[u].off - 1, mlen - MINMATCH, ultra);
+ else
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+ mlen++;
+ }
+ }
+ }
+
+ best_mlen = opt[last_pos].mlen;
+ best_off = opt[last_pos].off;
+ cur = last_pos - best_mlen;
+
+ /* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+ opt[0].mlen = 1;
+
+ while (1) {
+ mlen = opt[cur].mlen;
+ offset = opt[cur].off;
+ opt[cur].mlen = best_mlen;
+ opt[cur].off = best_off;
+ best_mlen = mlen;
+ best_off = offset;
+ if (mlen > cur)
+ break;
+ cur -= mlen;
+ }
+
+ for (u = 0; u <= last_pos;) {
+ u += opt[u].mlen;
+ }
+
+ for (cur = 0; cur < last_pos;) {
+ mlen = opt[cur].mlen;
+ if (mlen == 1) {
+ ip++;
+ cur++;
+ continue;
+ }
+ offset = opt[cur].off;
+ cur += mlen;
+ litLength = (U32)(ip - anchor);
+
+ if (offset > ZSTD_REP_MOVE_OPT) {
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
+ offset--;
+ } else {
+ if (offset != 0) {
+ best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+ if (offset != 1)
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = best_off;
+ }
+ if (litLength == 0)
+ offset--;
+ }
+
+ ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+ anchor = ip = ip + mlen;
+ }
+ } /* for (cur=0; cur < last_pos; ) */
+
+ /* Save reps for next block */
+ {
+ int i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ ctx->repToConfirm[i] = rep[i];
+ }
+
+ /* Last Literals */
+ {
+ size_t const lastLLSize = iend - anchor;
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
+ seqStorePtr->lit += lastLLSize;
+ }
+}
+
+FORCE_INLINE
+void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
+{
+ seqStore_t *seqStorePtr = &(ctx->seqStore);
+ const BYTE *const istart = (const BYTE *)src;
+ const BYTE *ip = istart;
+ const BYTE *anchor = istart;
+ const BYTE *const iend = istart + srcSize;
+ const BYTE *const ilimit = iend - 8;
+ const BYTE *const base = ctx->base;
+ const U32 lowestIndex = ctx->lowLimit;
+ const U32 dictLimit = ctx->dictLimit;
+ const BYTE *const prefixStart = base + dictLimit;
+ const BYTE *const dictBase = ctx->dictBase;
+ const BYTE *const dictEnd = dictBase + dictLimit;
+
+ const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
+ const U32 sufficient_len = ctx->params.cParams.targetLength;
+ const U32 mls = ctx->params.cParams.searchLength;
+ const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
+
+ ZSTD_optimal_t *opt = seqStorePtr->priceTable;
+ ZSTD_match_t *matches = seqStorePtr->matchTable;
+ const BYTE *inr;
+
+ /* init */
+ U32 offset, rep[ZSTD_REP_NUM];
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ rep[i] = ctx->rep[i];
+ }
+
+ ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
+ ip += (ip == prefixStart);
+
+ /* Match Loop */
+ while (ip < ilimit) {
+ U32 cur, match_num, last_pos, litlen, price;
+ U32 u, mlen, best_mlen, best_off, litLength;
+ U32 curr = (U32)(ip - base);
+ memset(opt, 0, sizeof(ZSTD_optimal_t));
+ last_pos = 0;
+ opt[0].litlen = (U32)(ip - anchor);
+
+ /* check repCode */
+ {
+ U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
+ for (i = (ip == anchor); i < last_i; i++) {
+ const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+ const U32 repIndex = (U32)(curr - repCur);
+ const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE *const repMatch = repBase + repIndex;
+ if ((repCur > 0 && repCur <= (S32)curr) &&
+ (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
+ /* repcode detected we should take it */
+ const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ mlen = (U32)ZSTD_count_2segments(ip + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
+
+ if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen;
+ best_off = i;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (ip == anchor);
+ litlen = opt[0].litlen;
+ do {
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+ mlen--;
+ } while (mlen >= minMatch);
+ }
+ }
+ }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
+
+ if (!last_pos && !match_num) {
+ ip++;
+ continue;
+ }
+
+ {
+ U32 i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ opt[0].rep[i] = rep[i];
+ }
+ opt[0].mlen = 1;
+
+ if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num - 1].len;
+ best_off = matches[match_num - 1].off;
+ cur = 0;
+ last_pos = 1;
+ goto _storeSequence;
+ }
+
+ best_mlen = (last_pos) ? last_pos : minMatch;
+
+ /* set prices using matches at position = 0 */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+ best_mlen = matches[u].len;
+ litlen = opt[0].litlen;
+ while (mlen <= best_mlen) {
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+ if (mlen > last_pos || price < opt[mlen].price)
+ SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
+ mlen++;
+ }
+ }
+
+ if (last_pos < minMatch) {
+ ip++;
+ continue;
+ }
+
+ /* check further positions */
+ for (cur = 1; cur <= last_pos; cur++) {
+ inr = ip + cur;
+
+ if (opt[cur - 1].mlen == 1) {
+ litlen = opt[cur - 1].litlen + 1;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
+ } else
+ price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
+ } else {
+ litlen = 1;
+ price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
+ }
+
+ if (cur > last_pos || price <= opt[cur].price)
+ SET_PRICE(cur, 1, 0, litlen, price);
+
+ if (cur == last_pos)
+ break;
+
+ if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+ continue;
+
+ mlen = opt[cur].mlen;
+ if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+ opt[cur].rep[2] = opt[cur - mlen].rep[1];
+ opt[cur].rep[1] = opt[cur - mlen].rep[0];
+ opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+ } else {
+ opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
+ opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
+ opt[cur].rep[0] =
+ ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
+ }
+
+ best_mlen = minMatch;
+ {
+ U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+ for (i = (mlen != 1); i < last_i; i++) {
+ const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+ const U32 repIndex = (U32)(curr + cur - repCur);
+ const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
+ const BYTE *const repMatch = repBase + repIndex;
+ if ((repCur > 0 && repCur <= (S32)(curr + cur)) &&
+ (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+ && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
+ /* repcode detected */
+ const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
+ mlen = (U32)ZSTD_count_2segments(inr + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
+
+ if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+ best_mlen = mlen;
+ best_off = i;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ best_off = i - (opt[cur].mlen != 1);
+ if (mlen > best_mlen)
+ best_mlen = mlen;
+
+ do {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen) {
+ price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
+ best_off, mlen - MINMATCH, ultra);
+ } else
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+ SET_PRICE(cur + mlen, mlen, i, litlen, price);
+ mlen--;
+ } while (mlen >= minMatch);
+ }
+ }
+ }
+
+ match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
+
+ if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+ best_mlen = matches[match_num - 1].len;
+ best_off = matches[match_num - 1].off;
+ last_pos = cur + 1;
+ goto _storeSequence;
+ }
+
+ /* set prices using matches at position = cur */
+ for (u = 0; u < match_num; u++) {
+ mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+ best_mlen = matches[u].len;
+
+ while (mlen <= best_mlen) {
+ if (opt[cur].mlen == 1) {
+ litlen = opt[cur].litlen;
+ if (cur > litlen)
+ price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
+ matches[u].off - 1, mlen - MINMATCH, ultra);
+ else
+ price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+ } else {
+ litlen = 0;
+ price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
+ }
+
+ if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+ SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+ mlen++;
+ }
+ }
+ } /* for (cur = 1; cur <= last_pos; cur++) */
+
+ best_mlen = opt[last_pos].mlen;
+ best_off = opt[last_pos].off;
+ cur = last_pos - best_mlen;
+
+ /* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+ opt[0].mlen = 1;
+
+ while (1) {
+ mlen = opt[cur].mlen;
+ offset = opt[cur].off;
+ opt[cur].mlen = best_mlen;
+ opt[cur].off = best_off;
+ best_mlen = mlen;
+ best_off = offset;
+ if (mlen > cur)
+ break;
+ cur -= mlen;
+ }
+
+ for (u = 0; u <= last_pos;) {
+ u += opt[u].mlen;
+ }
+
+ for (cur = 0; cur < last_pos;) {
+ mlen = opt[cur].mlen;
+ if (mlen == 1) {
+ ip++;
+ cur++;
+ continue;
+ }
+ offset = opt[cur].off;
+ cur += mlen;
+ litLength = (U32)(ip - anchor);
+
+ if (offset > ZSTD_REP_MOVE_OPT) {
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = offset - ZSTD_REP_MOVE_OPT;
+ offset--;
+ } else {
+ if (offset != 0) {
+ best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+ if (offset != 1)
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = best_off;
+ }
+
+ if (litLength == 0)
+ offset--;
+ }
+
+ ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+ ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+ anchor = ip = ip + mlen;
+ }
+ } /* for (cur=0; cur < last_pos; ) */
+
+ /* Save reps for next block */
+ {
+ int i;
+ for (i = 0; i < ZSTD_REP_NUM; i++)
+ ctx->repToConfirm[i] = rep[i];
+ }
+
+ /* Last Literals */
+ {
+ size_t lastLLSize = iend - anchor;
+ memcpy(seqStorePtr->lit, anchor, lastLLSize);
+ seqStorePtr->lit += lastLLSize;
+ }
+}
+
+#endif /* ZSTD_OPT_H_91842398743 */