Merge branch '2022-01-28-assorted-fixes'

- Extend the pci command to support a few more features.
- Add support for custom SPL boot device names (so it's easier for users
  to understand)
- Updates for am64x to address some review comments.
- Migration deadline notice for DM_SERIAL
- coreboot payload test
- Support rsa3072 signatures.
- DFU should skip writing empty UBI pages, bootcount printf format char
  correction.
This commit is contained in:
Tom Rini 2022-01-29 13:42:58 -05:00
commit 98a90b2730
24 changed files with 265 additions and 39 deletions

View file

@ -222,6 +222,10 @@ stages:
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
sandbox_flattree:
TEST_PY_BD: "sandbox_flattree"
coreboot:
TEST_PY_BD: "coreboot"
TEST_PY_ID: "--id qemu"
TEST_PY_TEST_SPEC: "not sleep"
evb_ast2500:
TEST_PY_BD: "evb-ast2500"
TEST_PY_ID: "--id qemu"
@ -353,6 +357,12 @@ stages:
genimage --inputpath . --config board/sifive/unleashed/genimage_spi-nor.cfg;
cp images/spi-nor.img ${UBOOT_TRAVIS_BUILD_DIR}/;
fi
if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
wget -O - "https://drive.google.com/uc?id=1x6nrtWIyIRPLS2cQBwYTnT2TbOI8UjmM&export=download" |xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom;
wget -O - "https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=download" >cbfstool;
chmod a+x cbfstool;
./cbfstool ${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom add-flat-binary -f ${UBOOT_TRAVIS_BUILD_DIR}/u-boot.bin -n fallback/payload -c LZMA -l 0x1110000 -e 0x1110000;
fi
virtualenv -p /usr/bin/python3 /tmp/venv
. /tmp/venv/bin/activate
pip install -r test/py/requirements.txt

View file

@ -52,6 +52,16 @@ stages:
genimage --inputpath . --config board/sifive/unleashed/genimage_spi-nor.cfg;
cp images/spi-nor.img ${UBOOT_TRAVIS_BUILD_DIR}/;
fi
- if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
wget -O -
"https://drive.google.com/uc?id=1x6nrtWIyIRPLS2cQBwYTnT2TbOI8UjmM&export=download" |
xz -dc >${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom;
wget -O -
"https://drive.google.com/uc?id=149Cz-5SZXHNKpi9xg6R_5XITWohu348y&export=download" >
cbfstool;
chmod a+x cbfstool;
./cbfstool ${UBOOT_TRAVIS_BUILD_DIR}/coreboot.rom add-flat-binary -f ${UBOOT_TRAVIS_BUILD_DIR}/u-boot.bin -n fallback/payload -c LZMA -l 0x1110000 -e 0x1110000;
fi
- virtualenv -p /usr/bin/python3 /tmp/venv
- . /tmp/venv/bin/activate
- pip install -r test/py/requirements.txt
@ -61,6 +71,10 @@ stages:
./test/py/test.py -ra --bd ${TEST_PY_BD} ${TEST_PY_ID}
${TEST_PY_TEST_SPEC:+"-k ${TEST_PY_TEST_SPEC}"}
--build-dir "$UBOOT_TRAVIS_BUILD_DIR"
# It seems that the files in /tmp go away, so copy out what we need
- if [[ "${TEST_PY_BD}" == "coreboot" ]]; then
cp -v /tmp/coreboot/*.{html,css} .;
fi
build all 32bit ARM platforms:
stage: world build
@ -387,3 +401,15 @@ xtfpga test.py:
TEST_PY_TEST_SPEC: "not sleep"
TEST_PY_ID: "--id qemu"
<<: *buildman_and_testpy_dfn
coreboot test.py:
variables:
TEST_PY_BD: "coreboot"
TEST_PY_TEST_SPEC: "not sleep"
TEST_PY_ID: "--id qemu"
artifacts:
paths:
- "*.html"
- "*.css"
expire_in: 1 week
<<: *buildman_and_testpy_dfn

View file

@ -1133,6 +1133,7 @@ endif
@# confuses this rule. Use if() to send just a single character which
@# is enable to tell 'deprecated' that one of these symbols exists
$(call deprecated,CONFIG_TIMER,Timer drivers,v2023.01,$(if $(strip $(CONFIG_SYS_TIMER_RATE)$(CONFIG_SYS_TIMER_COUNTER)),x))
$(call deprecated,CONFIG_DM_SERIAL,Serial drivers,v2023.04,$(CONFIG_SERIAL))
@# Check that this build does not use CONFIG options that we do not
@# know about unless they are in Kconfig. All the existing CONFIG
@# options are whitelisted, so new ones should not be added.

View file

@ -231,23 +231,12 @@
&rgmii2_pins_default>;
};
&cpsw_port1 {
phy-mode = "rgmii-rxid";
phy-handle = <&cpsw3g_phy0>;
};
&cpsw_port2 {
phy-mode = "rgmii-rxid";
phy-handle = <&cpsw3g_phy1>;
};
&cpsw3g_mdio {
cpsw3g_phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
cpsw3g_phy1: ethernet-phy@1 {
reg = <1>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;

View file

@ -117,10 +117,6 @@
u-boot,dm-spl;
};
&cpsw_port1 {
u-boot,dm-spl;
};
&main_bcdma {
u-boot,dm-spl;
};
@ -141,10 +137,6 @@
u-boot,dm-spl;
};
&cpsw3g_phy0 {
u-boot,dm-spl;
};
&cpsw3g_phy1 {
u-boot,dm-spl;
};

View file

@ -256,10 +256,8 @@ static void pci_header_show(struct udevice *dev)
}
}
static void pciinfo_header(int busnum, bool short_listing)
static void pciinfo_header(bool short_listing)
{
printf("Scanning PCI devices on bus %d\n", busnum);
if (short_listing) {
printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
printf("_____________________________________________________________\n");
@ -288,11 +286,15 @@ static void pci_header_show_brief(struct udevice *dev)
pci_class_str(class), subclass);
}
static void pciinfo(struct udevice *bus, bool short_listing)
static void pciinfo(struct udevice *bus, bool short_listing, bool multi)
{
struct udevice *dev;
pciinfo_header(dev_seq(bus), short_listing);
if (!multi)
printf("Scanning PCI devices on bus %d\n", dev_seq(bus));
if (!multi || dev_seq(bus) == 0)
pciinfo_header(short_listing);
for (device_find_first_child(bus, &dev);
dev;
@ -443,7 +445,7 @@ static const struct pci_flag_info {
static void pci_show_regions(struct udevice *bus)
{
struct pci_controller *hose = dev_get_uclass_priv(bus);
struct pci_controller *hose = dev_get_uclass_priv(pci_get_controller(bus));
const struct pci_region *reg;
int i, j;
@ -452,6 +454,7 @@ static void pci_show_regions(struct udevice *bus)
return;
}
printf("Buses %02x-%02x\n", hose->first_busno, hose->last_busno);
printf("# %-18s %-18s %-18s %s\n", "Bus start", "Phys start", "Size",
"Flags");
for (i = 0, reg = hose->regions; i < hose->region_count; i++, reg++) {
@ -482,10 +485,11 @@ static int do_pci(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
ulong addr = 0, value = 0, cmd_size = 0;
enum pci_size_t size = PCI_SIZE_32;
struct udevice *dev, *bus;
int busnum = 0;
int busnum = -1;
pci_dev_t bdf = 0;
char cmd = 's';
int ret = 0;
char *endp;
if (argc > 1)
cmd = argv[1][0];
@ -520,8 +524,36 @@ static int do_pci(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
value = 0;
argc--;
}
if (argc > 1)
busnum = hextoul(argv[1], NULL);
if (argc > 2 || (argc > 1 && cmd != 'r' && argv[1][0] != 's')) {
if (argv[argc - 1][0] != '*') {
busnum = hextoul(argv[argc - 1], &endp);
if (*endp)
goto usage;
}
argc--;
}
if (cmd == 'r' && argc > 2)
goto usage;
else if (cmd != 'r' && (argc > 2 || (argc == 2 && argv[1][0] != 's')))
goto usage;
}
if (busnum == -1) {
if (cmd != 'r') {
for (busnum = 0;
uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus) == 0;
busnum++)
pciinfo(bus, value, true);
} else {
for (busnum = 0;
uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus) == 0;
busnum++) {
/* Regions are controller specific so skip non-root buses */
if (device_is_on_pci_bus(bus))
continue;
pci_show_regions(bus);
}
}
return 0;
}
ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus);
if (ret) {
@ -531,7 +563,7 @@ static int do_pci(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (cmd == 'r')
pci_show_regions(bus);
else
pciinfo(bus, value);
pciinfo(bus, value, false);
return 0;
}
@ -578,7 +610,7 @@ static int do_pci(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
#ifdef CONFIG_SYS_LONGHELP
static char pci_help_text[] =
"[bus] [long]\n"
"[bus|*] [long]\n"
" - short or long list of PCI devices on bus 'bus'\n"
"pci enum\n"
" - Enumerate PCI buses\n"
@ -586,7 +618,7 @@ static char pci_help_text[] =
" - show header of PCI device 'bus.device.function'\n"
"pci bar b.d.f\n"
" - show BARs base and size for device b.d.f'\n"
"pci regions\n"
"pci regions [bus|*]\n"
" - show PCI regions\n"
"pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
" - display PCI configuration space (CFG)\n"

View file

@ -174,6 +174,11 @@ __weak void spl_board_prepare_for_optee(void *fdt)
{
}
__weak const char *spl_board_loader_name(u32 boot_device)
{
return NULL;
}
#if CONFIG_IS_ENABLED(OPTEE_IMAGE)
__weak void __noreturn jump_to_image_optee(struct spl_image_info *spl_image)
{

View file

@ -30,6 +30,7 @@ CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
CONFIG_BOARD_LATE_INIT=y
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
@ -38,8 +39,11 @@ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
CONFIG_SPL_DMA=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_ETH=y
CONFIG_SPL_DM_MAILBOX=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_NET=y
CONFIG_SPL_NET_VCI_STRING="AM64X U-Boot A53 SPL"
CONFIG_SPL_POWER_DOMAIN=y
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_SPL_RAM_DEVICE=y

View file

@ -38,10 +38,14 @@ CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SPL_EARLY_BSS=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
CONFIG_SPL_DMA=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_ETH=y
CONFIG_SPL_DM_MAILBOX=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_NET=y
CONFIG_SPL_NET_VCI_STRING="AM64X U-Boot R5 SPL"
CONFIG_SPL_DM_RESET=y
CONFIG_SPL_POWER_DOMAIN=y
CONFIG_SPL_RAM_SUPPORT=y
@ -63,6 +67,7 @@ CONFIG_CMD_REMOTEPROC=y
CONFIG_CMD_USB=y
CONFIG_CMD_USB_MASS_STORAGE=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_TIME=y
CONFIG_CMD_FAT=y
CONFIG_OF_CONTROL=y
@ -90,12 +95,15 @@ CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x5000
CONFIG_DMA_CHANNELS=y
CONFIG_TI_K3_NAVSS_UDMA=y
CONFIG_TI_SCI_PROTOCOL=y
CONFIG_DA8XX_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_OMAP24XX=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
CONFIG_SPL_MISC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
@ -108,6 +116,9 @@ CONFIG_SPL_PHY=y
CONFIG_PHY_CADENCE_SIERRA=y
CONFIG_PHY_CADENCE_TORRENT=y
CONFIG_PHY_J721E_WIZ=y
CONFIG_PHY_TI_DP83867=y
CONFIG_DM_ETH=y
CONFIG_TI_AM65_CPSW_NUSS=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_SPL_PINCTRL=y
@ -125,6 +136,7 @@ CONFIG_DM_RESET=y
CONFIG_RESET_TI_SCI=y
CONFIG_SPECIFY_CONSOLE_INDEX=y
CONFIG_DM_SERIAL=y
CONFIG_SOC_TI=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_CADENCE_QSPI=y

View file

@ -312,3 +312,4 @@ CONFIG_TEST_FDTDEC=y
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
CONFIG_SHA384=y

View file

@ -118,3 +118,11 @@ other base driver model options in time for inclusion in the 2022.10 release.
There is only one method to implement, unless you want to support bootstage,
in which case you need an early timer also. For example drivers, see
sandbox_timer.c and rockchip_timer.c
CONFIG_DM_SERIAL
----------------
Deadline: 2023.04
The serial subsystem has supported the driver model since late 2014.
Maintainers should submit patches switching over to using CONFIG_DM_SERIAL and
other base driver model options in time for inclusion in the 2022.10 release.

View file

@ -107,8 +107,8 @@ static int bootcount_syscon_of_to_plat(struct udevice *dev)
return -EINVAL;
}
if (reg_size != 4) {
dev_err(dev, "%s: Unsupported register size: %d\n", __func__,
reg_size);
dev_err(dev, "%s: Unsupported register size: %pa\n", __func__,
&reg_size);
return -EINVAL;
}

View file

@ -18,6 +18,20 @@ static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
return !do_div(size, mtd->erasesize);
}
/* Logic taken from cmd/mtd.c:mtd_oob_write_is_empty() */
static bool mtd_page_is_empty(struct mtd_oob_ops *op)
{
int i;
for (i = 0; i < op->len; i++)
if (op->datbuf[i] != 0xff)
return false;
/* oob is not used, with MTD_OPS_AUTO_OOB & ooblen=0 */
return true;
}
static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
{
@ -129,8 +143,14 @@ static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu,
if (op == DFU_OP_READ)
ret = mtd_read_oob(mtd, off, &io_op);
else
else if (has_pages && dfu->data.mtd.ubi && mtd_page_is_empty(&io_op)) {
/* in case of ubi partition, do not write an empty page, only skip it */
ret = 0;
io_op.retlen = mtd->writesize;
io_op.oobretlen = mtd->oobsize;
} else {
ret = mtd_write_oob(mtd, off, &io_op);
}
if (ret) {
printf("Failure while %s at offset 0x%llx\n",

View file

@ -752,7 +752,7 @@ static int am65_cpsw_probe_nuss(struct udevice *dev)
ret = device_bind_driver_to_node(dev, "am65_cpsw_nuss_port", ofnode_get_name(node), node, &port_dev);
if (ret)
printf("SCREEEM\n");
dev_err(dev, "Failed to bind to %s node\n", ofnode_get_name(node));
}
for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {

View file

@ -560,6 +560,8 @@ int pci_auto_config_devices(struct udevice *bus)
if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
set_vga_bridge_bits(dev);
}
if (hose->last_busno < sub_bus)
hose->last_busno = sub_bus;
debug("%s: done\n", __func__);
return log_msg_ret("sub", sub_bus);

View file

@ -728,6 +728,8 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
*inode_table = malloc(metablks_count * SQFS_METADATA_BLOCK_SIZE);
if (!*inode_table) {
ret = -ENOMEM;
printf("Error: failed to allocate squashfs inode_table of size %i, increasing CONFIG_SYS_MALLOC_LEN could help\n",
metablks_count * SQFS_METADATA_BLOCK_SIZE);
goto free_itb;
}

View file

@ -33,7 +33,7 @@
* our memory footprint. The less we use for BSS the more we have available
* for everything else.
*/
#define CONFIG_SPL_BSS_MAX_SIZE 0x1000
#define CONFIG_SPL_BSS_MAX_SIZE 0x4000
/*
* Link BSS to be within SPL in a dedicated region located near the top of
* the MCU SRAM, this way making it available also before relocation. Note

View file

@ -462,6 +462,17 @@ void spl_board_prepare_for_boot(void);
int spl_board_ubi_load_image(u32 boot_device);
int spl_board_boot_device(u32 boot_device);
/**
* spl_board_loader_name() - Return a name for the loader
*
* This is a weak function which might be overridden by the board code. With
* that a board specific value for the device where the U-Boot will be loaded
* from can be set. By default it returns NULL.
*
* @boot_device: ID of the device which SPL wants to load U-Boot from.
*/
const char *spl_board_loader_name(u32 boot_device);
/**
* jump_to_image_linux() - Jump to a Linux kernel from SPL
*
@ -544,7 +555,9 @@ struct spl_image_loader {
static inline const char *spl_loader_name(const struct spl_image_loader *loader)
{
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
return loader->name;
const char *name;
name = spl_board_loader_name(loader->boot_device);
return name ?: loader->name;
#else
return NULL;
#endif

View file

@ -111,6 +111,7 @@ int padding_pss_verify(struct image_sign_info *info,
#define RSA_DEFAULT_PADDING_NAME "pkcs-1.5"
#define RSA2048_BYTES (2048 / 8)
#define RSA3072_BYTES (3072 / 8)
#define RSA4096_BYTES (4096 / 8)
/* This is the minimum/maximum key size we support, in bits */

View file

@ -595,6 +595,12 @@ U_BOOT_CRYPTO_ALGO(rsa2048) = {
.verify = rsa_verify,
};
U_BOOT_CRYPTO_ALGO(rsa3072) = {
.name = "rsa3072",
.key_len = RSA3072_BYTES,
.verify = rsa_verify,
};
U_BOOT_CRYPTO_ALGO(rsa4096) = {
.name = "rsa4096",
.key_len = RSA4096_BYTES,

View file

@ -45,6 +45,8 @@ TESTDATA = [
['sha256-pss-pad', 'sha256', '-pss', '-E -p 0x10000', False, False],
['sha256-pss-required', 'sha256', '-pss', None, True, False],
['sha256-pss-pad-required', 'sha256', '-pss', '-E -p 0x10000', True, True],
['sha384-basic', 'sha384', '', None, False, False],
['sha384-pad', 'sha384', '', '-E -p 0x10000', False, False],
]
@pytest.mark.boardspec('sandbox')
@ -180,10 +182,16 @@ def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, required,
name: Name of of the key (e.g. 'dev')
"""
public_exponent = 65537
if sha_algo == "sha384":
rsa_keygen_bits = 3072
else:
rsa_keygen_bits = 2048
util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %s%s.key '
'-pkeyopt rsa_keygen_bits:2048 '
'-pkeyopt rsa_keygen_bits:%d '
'-pkeyopt rsa_keygen_pubexp:%d' %
(tmpdir, name, public_exponent))
(tmpdir, name, rsa_keygen_bits, public_exponent))
# Create a certificate containing the public key
util.run_and_log(cons, 'openssl req -batch -new -x509 -key %s%s.key '

View file

@ -0,0 +1,45 @@
/dts-v1/;
/ {
description = "Chrome OS kernel image with one or more FDT blobs";
#address-cells = <1>;
images {
kernel {
data = /incbin/("test-kernel.bin");
type = "kernel_noload";
arch = "sandbox";
os = "linux";
compression = "none";
load = <0x4>;
entry = <0x8>;
kernel-version = <1>;
hash-1 {
algo = "sha384";
};
};
fdt-1 {
description = "snow";
data = /incbin/("sandbox-kernel.dtb");
type = "flat_dt";
arch = "sandbox";
compression = "none";
fdt-version = <1>;
hash-1 {
algo = "sha384";
};
};
};
configurations {
default = "conf-1";
conf-1 {
kernel = "kernel";
fdt = "fdt-1";
signature {
algo = "sha384,rsa3072";
key-name-hint = "dev";
sign-images = "fdt", "kernel";
};
};
};
};

View file

@ -0,0 +1,42 @@
/dts-v1/;
/ {
description = "Chrome OS kernel image with one or more FDT blobs";
#address-cells = <1>;
images {
kernel {
data = /incbin/("test-kernel.bin");
type = "kernel_noload";
arch = "sandbox";
os = "linux";
compression = "none";
load = <0x4>;
entry = <0x8>;
kernel-version = <1>;
signature {
algo = "sha384,rsa3072";
key-name-hint = "dev";
};
};
fdt-1 {
description = "snow";
data = /incbin/("sandbox-kernel.dtb");
type = "flat_dt";
arch = "sandbox";
compression = "none";
fdt-version = <1>;
signature {
algo = "sha384,rsa3072";
key-name-hint = "dev";
};
};
};
configurations {
default = "conf-1";
conf-1 {
kernel = "kernel";
fdt = "fdt-1";
};
};
};

View file

@ -55,6 +55,13 @@ struct crypto_algo crypto_algos[] = {
.add_verify_data = rsa_add_verify_data,
.verify = rsa_verify,
},
{
.name = "rsa3072",
.key_len = RSA3072_BYTES,
.sign = rsa_sign,
.add_verify_data = rsa_add_verify_data,
.verify = rsa_verify,
},
{
.name = "rsa4096",
.key_len = RSA4096_BYTES,