mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-03 10:17:21 +00:00
Merge branch '2024-03-02-assorted-updates' into next
- Assorted MediaTek, ASPEED, xenguest, s5p4418 and qemu-arm fixes - Assorted test fixes/updates/additions. - A few bootstd/related fixes. - Remove common.h from some files - Drop reiserfs - A few other assorted fixes throughout the tree.
This commit is contained in:
commit
bd465ada0e
69 changed files with 551 additions and 2056 deletions
3
Makefile
3
Makefile
|
@ -1831,7 +1831,8 @@ ENV_FILE := $(if $(ENV_SOURCE_FILE),$(ENV_FILE_CFG),$(wildcard $(ENV_FILE_BOARD)
|
||||||
quiet_cmd_gen_envp = ENVP $@
|
quiet_cmd_gen_envp = ENVP $@
|
||||||
cmd_gen_envp = \
|
cmd_gen_envp = \
|
||||||
if [ -s "$(ENV_FILE)" ]; then \
|
if [ -s "$(ENV_FILE)" ]; then \
|
||||||
$(CPP) -P $(CFLAGS) -x assembler-with-cpp -D__ASSEMBLY__ \
|
$(CPP) -P $(CFLAGS) -x assembler-with-cpp -undef \
|
||||||
|
-D__ASSEMBLY__ \
|
||||||
-D__UBOOT_CONFIG__ \
|
-D__UBOOT_CONFIG__ \
|
||||||
-I . -I include -I $(srctree)/include \
|
-I . -I include -I $(srctree)/include \
|
||||||
-include linux/kconfig.h -include include/config.h \
|
-include linux/kconfig.h -include include/config.h \
|
||||||
|
|
|
@ -699,15 +699,6 @@ config TARGET_BCMNS
|
||||||
ARMv7 Cortex-A9 SoC family including BCM4708, BCM47094,
|
ARMv7 Cortex-A9 SoC family including BCM4708, BCM47094,
|
||||||
BCM5301x etc.
|
BCM5301x etc.
|
||||||
|
|
||||||
config TARGET_BCMNS2
|
|
||||||
bool "Support Broadcom Northstar2"
|
|
||||||
select ARM64
|
|
||||||
select GPIO_EXTRA_HEADER
|
|
||||||
help
|
|
||||||
Support for Broadcom Northstar 2 SoCs. NS2 is a quad-core 64-bit
|
|
||||||
ARMv8 Cortex-A57 processors targeting a broad range of networking
|
|
||||||
applications.
|
|
||||||
|
|
||||||
config TARGET_BCMNS3
|
config TARGET_BCMNS3
|
||||||
bool "Support Broadcom NS3"
|
bool "Support Broadcom NS3"
|
||||||
select ARM64
|
select ARM64
|
||||||
|
|
|
@ -2,5 +2,8 @@
|
||||||
#
|
#
|
||||||
# (C) Copyright 2016 Nexell
|
# (C) Copyright 2016 Nexell
|
||||||
# Hyunseok, Jung <hsjung@nexell.co.kr>
|
# Hyunseok, Jung <hsjung@nexell.co.kr>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023 Stefan Bosch <stefan_b@posteo.net>
|
||||||
|
|
||||||
obj-y += cpu.o
|
obj-y += cpu.o
|
||||||
|
obj-y += relocate.o
|
||||||
|
|
24
arch/arm/cpu/armv7/s5p4418/relocate.S
Normal file
24
arch/arm/cpu/armv7/s5p4418/relocate.S
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* relocate - S5P4418 specific relocation for ARM U-Boot
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
|
||||||
|
* Copyright (C) 2023 Stefan Bosch <stefan_b@posteo.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <asm/assembler.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
ENTRY(relocate_vectors)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The s5p4418 SoC has the security extensions, so use VBAR to relocate
|
||||||
|
* the exception vectors.
|
||||||
|
*/
|
||||||
|
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
|
||||||
|
add r0, #0x400 /* vectors are after NSIH + 0x200 */
|
||||||
|
mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */
|
||||||
|
ret lr
|
||||||
|
|
||||||
|
ENDPROC(relocate_vectors)
|
|
@ -2028,6 +2028,26 @@
|
||||||
groups = "SPI2MOSI";
|
groups = "SPI2MOSI";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pinctrl_thru0_default: thru0_default {
|
||||||
|
function = "THRU0";
|
||||||
|
groups = "THRU0";
|
||||||
|
};
|
||||||
|
|
||||||
|
pinctrl_thru1_default: thru1_default {
|
||||||
|
function = "THRU1";
|
||||||
|
groups = "THRU1";
|
||||||
|
};
|
||||||
|
|
||||||
|
pinctrl_thru2_default: thru2_default {
|
||||||
|
function = "THRU2";
|
||||||
|
groups = "THRU2";
|
||||||
|
};
|
||||||
|
|
||||||
|
pinctrl_thru3_default: thru3_default {
|
||||||
|
function = "THRU3";
|
||||||
|
groups = "THRU3";
|
||||||
|
};
|
||||||
|
|
||||||
pinctrl_timer3_default: timer3_default {
|
pinctrl_timer3_default: timer3_default {
|
||||||
function = "TIMER3";
|
function = "TIMER3";
|
||||||
groups = "TIMER3";
|
groups = "TIMER3";
|
||||||
|
|
|
@ -87,10 +87,12 @@
|
||||||
pins = "SPI2_CSB", "SPI2_MISO", "SPI2_MOSI",
|
pins = "SPI2_CSB", "SPI2_MISO", "SPI2_MOSI",
|
||||||
"SPI2_CLK", "SPI2_HOLD";
|
"SPI2_CLK", "SPI2_HOLD";
|
||||||
input-enable;
|
input-enable;
|
||||||
|
drive-strength = <MTK_DRIVE_4mA>;
|
||||||
};
|
};
|
||||||
|
|
||||||
conf-clk {
|
conf-clk {
|
||||||
pins = "SPI2_WP";
|
pins = "SPI2_WP";
|
||||||
|
drive-strength = <MTK_DRIVE_4mA>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <dt-bindings/clock/mt7988-clk.h>
|
#include <dt-bindings/clock/mt7988-clk.h>
|
||||||
#include <dt-bindings/reset/mt7988-reset.h>
|
#include <dt-bindings/reset/mt7988-reset.h>
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/pinctrl/mt65xx.h>
|
||||||
#include <dt-bindings/phy/phy.h>
|
#include <dt-bindings/phy/phy.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
|
|
@ -127,6 +127,18 @@ int dram_init(void)
|
||||||
if (fdtdec_setup_mem_size_base() != 0)
|
if (fdtdec_setup_mem_size_base() != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When LPAE is enabled (ARMv7),
|
||||||
|
* 1:1 mapping is created using 2 MB blocks.
|
||||||
|
*
|
||||||
|
* In case amount of memory provided to QEMU
|
||||||
|
* is not multiple of 2 MB, round down the amount
|
||||||
|
* of available memory to avoid hang during MMU
|
||||||
|
* initialization.
|
||||||
|
*/
|
||||||
|
if (CONFIG_IS_ENABLED(ARMV7_LPAE))
|
||||||
|
gd->ram_size -= (gd->ram_size % 0x200000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
DEVELOPER BOX
|
DEVELOPER BOX
|
||||||
M: Jassi Brar <jaswinder.singh@linaro.org>
|
M: Masahisa Kojima <kojima.masahisa@socionext.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/dts/synquacer-*
|
F: arch/arm/dts/synquacer-*
|
||||||
F: board/socionext/developerbox/*
|
F: board/socionext/developerbox/*
|
||||||
|
|
|
@ -35,3 +35,34 @@ void set_dfu_alt_info(char *interface, char *devstr)
|
||||||
|
|
||||||
env_set("dfu_alt_info", buf);
|
env_set("dfu_alt_info", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fwu_plat_get_bootidx() - Get the value of the boot index
|
||||||
|
* @boot_idx: Boot index value
|
||||||
|
*
|
||||||
|
* Get the value of the bank(partition) from which the platform
|
||||||
|
* has booted. This value is passed to U-Boot from the earlier
|
||||||
|
* stage bootloader which loads and boots all the relevant
|
||||||
|
* firmware images
|
||||||
|
*/
|
||||||
|
void fwu_plat_get_bootidx(uint *boot_idx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 buf;
|
||||||
|
size_t readlen;
|
||||||
|
struct mtd_info *mtd;
|
||||||
|
|
||||||
|
*boot_idx = 0;
|
||||||
|
|
||||||
|
mtd_probe_devices();
|
||||||
|
mtd = get_mtd_device_nm("nor1");
|
||||||
|
if (IS_ERR_OR_NULL(mtd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = mtd_read(mtd, SCB_PLAT_METADATA_OFFSET, sizeof(buf),
|
||||||
|
&readlen, (u_char *)&buf);
|
||||||
|
if (ret < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*boot_idx = buf;
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#define GUEST_VIRTIO_MMIO_BASE 0x2000000
|
||||||
|
#define GUEST_VIRTIO_MMIO_SIZE 0x100000
|
||||||
|
|
||||||
int board_init(void)
|
int board_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -212,6 +215,15 @@ static int setup_mem_map(void)
|
||||||
PTE_BLOCK_INNER_SHARE);
|
PTE_BLOCK_INNER_SHARE);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(VIRTIO_MMIO)) {
|
||||||
|
xen_mem_map[i].virt = GUEST_VIRTIO_MMIO_BASE;
|
||||||
|
xen_mem_map[i].phys = GUEST_VIRTIO_MMIO_BASE;
|
||||||
|
xen_mem_map[i].size = GUEST_VIRTIO_MMIO_SIZE;
|
||||||
|
xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||||
|
PTE_BLOCK_NON_SHARE);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
mem = get_next_memory_node(blob, -1);
|
mem = get_next_memory_node(blob, -1);
|
||||||
if (mem < 0) {
|
if (mem < 0) {
|
||||||
printf("%s: Missing /memory node\n", __func__);
|
printf("%s: Missing /memory node\n", __func__);
|
||||||
|
@ -219,6 +231,11 @@ static int setup_mem_map(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < MAX_MEM_MAP_REGIONS; i++) {
|
for (; i < MAX_MEM_MAP_REGIONS; i++) {
|
||||||
|
if (CONFIG_IS_ENABLED(VIRTIO_MMIO)) {
|
||||||
|
ret = fdt_node_check_compatible(blob, mem, "virtio,mmio");
|
||||||
|
if (!ret)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
|
ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
|
||||||
if (ret == -FDT_ERR_NOTFOUND) {
|
if (ret == -FDT_ERR_NOTFOUND) {
|
||||||
reg = 0;
|
reg = 0;
|
||||||
|
|
|
@ -39,7 +39,6 @@ int bootdev_add_bootflow(struct bootflow *bflow)
|
||||||
struct bootflow *new;
|
struct bootflow *new;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(bflow->dev);
|
|
||||||
ret = bootstd_get_priv(&std);
|
ret = bootstd_get_priv(&std);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -173,8 +172,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
|
||||||
*/
|
*/
|
||||||
iter->max_part = MAX_PART_PER_BOOTDEV;
|
iter->max_part = MAX_PART_PER_BOOTDEV;
|
||||||
|
|
||||||
/* If this is the whole disk, check if we have bootable partitions */
|
if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION) {
|
||||||
if (!iter->part) {
|
/* a particular partition was specified, scan it without checking */
|
||||||
|
} else if (!iter->part) {
|
||||||
|
/* This is the whole disk, check if we have bootable partitions */
|
||||||
iter->first_bootable = part_get_bootable(desc);
|
iter->first_bootable = part_get_bootable(desc);
|
||||||
log_debug("checking bootable=%d\n", iter->first_bootable);
|
log_debug("checking bootable=%d\n", iter->first_bootable);
|
||||||
} else if (allow_any_part) {
|
} else if (allow_any_part) {
|
||||||
|
@ -711,8 +712,37 @@ int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
|
||||||
struct udevice *bootstd, *dev = NULL;
|
struct udevice *bootstd, *dev = NULL;
|
||||||
bool show = iter->flags & BOOTFLOWIF_SHOW;
|
bool show = iter->flags & BOOTFLOWIF_SHOW;
|
||||||
int method_flags;
|
int method_flags;
|
||||||
|
char buf[32];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
const char *end = strchr(label, ':');
|
||||||
|
|
||||||
|
if (end) {
|
||||||
|
size_t len = (size_t)(end - label);
|
||||||
|
const char *part = end + 1;
|
||||||
|
|
||||||
|
if (len + 1 > sizeof(buf)) {
|
||||||
|
log_err("label \"%s\" is way too long\n", label);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, label, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
label = buf;
|
||||||
|
|
||||||
|
unsigned long tmp;
|
||||||
|
|
||||||
|
if (strict_strtoul(part, 0, &tmp)) {
|
||||||
|
log_err("Invalid partition number: %s\n", part);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->flags |= BOOTFLOWIF_SINGLE_PARTITION;
|
||||||
|
iter->part = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
|
ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
log_err("Missing bootstd device\n");
|
log_err("Missing bootstd device\n");
|
||||||
|
|
|
@ -217,6 +217,9 @@ static int iter_incr(struct bootflow_iter *iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION)
|
||||||
|
return BF_NO_MORE_DEVICES;
|
||||||
|
|
||||||
/* No more bootmeths; start at the first one, and... */
|
/* No more bootmeths; start at the first one, and... */
|
||||||
iter->cur_method = 0;
|
iter->cur_method = 0;
|
||||||
iter->method = iter->method_order[iter->cur_method];
|
iter->method = iter->method_order[iter->cur_method];
|
||||||
|
|
|
@ -17,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
#define IMAGE_MAX_HASHED_NODES 100
|
#define IMAGE_MAX_HASHED_NODES 100
|
||||||
|
|
||||||
struct checksum_algo checksum_algos[] = {
|
struct checksum_algo checksum_algos[] = {
|
||||||
|
#if CONFIG_IS_ENABLED(SHA1)
|
||||||
{
|
{
|
||||||
.name = "sha1",
|
.name = "sha1",
|
||||||
.checksum_len = SHA1_SUM_LEN,
|
.checksum_len = SHA1_SUM_LEN,
|
||||||
|
@ -24,6 +25,8 @@ struct checksum_algo checksum_algos[] = {
|
||||||
.der_prefix = sha1_der_prefix,
|
.der_prefix = sha1_der_prefix,
|
||||||
.calculate = hash_calculate,
|
.calculate = hash_calculate,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
|
#if CONFIG_IS_ENABLED(SHA256)
|
||||||
{
|
{
|
||||||
.name = "sha256",
|
.name = "sha256",
|
||||||
.checksum_len = SHA256_SUM_LEN,
|
.checksum_len = SHA256_SUM_LEN,
|
||||||
|
@ -31,7 +34,8 @@ struct checksum_algo checksum_algos[] = {
|
||||||
.der_prefix = sha256_der_prefix,
|
.der_prefix = sha256_der_prefix,
|
||||||
.calculate = hash_calculate,
|
.calculate = hash_calculate,
|
||||||
},
|
},
|
||||||
#ifdef CONFIG_SHA384
|
#endif
|
||||||
|
#if CONFIG_IS_ENABLED(SHA384)
|
||||||
{
|
{
|
||||||
.name = "sha384",
|
.name = "sha384",
|
||||||
.checksum_len = SHA384_SUM_LEN,
|
.checksum_len = SHA384_SUM_LEN,
|
||||||
|
@ -40,7 +44,7 @@ struct checksum_algo checksum_algos[] = {
|
||||||
.calculate = hash_calculate,
|
.calculate = hash_calculate,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SHA512
|
#if CONFIG_IS_ENABLED(SHA512)
|
||||||
{
|
{
|
||||||
.name = "sha512",
|
.name = "sha512",
|
||||||
.checksum_len = SHA512_SUM_LEN,
|
.checksum_len = SHA512_SUM_LEN,
|
||||||
|
|
|
@ -634,7 +634,12 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
|
||||||
char *fdtfilefree = NULL;
|
char *fdtfilefree = NULL;
|
||||||
|
|
||||||
if (label->fdt) {
|
if (label->fdt) {
|
||||||
fdtfile = label->fdt;
|
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
|
||||||
|
if (strcmp("-", label->fdt))
|
||||||
|
fdtfile = label->fdt;
|
||||||
|
} else {
|
||||||
|
fdtfile = label->fdt;
|
||||||
|
}
|
||||||
} else if (label->fdtdir) {
|
} else if (label->fdtdir) {
|
||||||
char *f1, *f2, *f3, *f4, *slash;
|
char *f1, *f2, *f3, *f4, *slash;
|
||||||
|
|
||||||
|
@ -731,14 +736,26 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
|
||||||
zboot_argc = 5;
|
zboot_argc = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bootm_argv[3])
|
if (!bootm_argv[3]) {
|
||||||
bootm_argv[3] = env_get("fdt_addr");
|
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
|
||||||
|
if (strcmp("-", label->fdt))
|
||||||
|
bootm_argv[3] = env_get("fdt_addr");
|
||||||
|
} else {
|
||||||
|
bootm_argv[3] = env_get("fdt_addr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kernel_addr_r = genimg_get_kernel_addr(kernel_addr);
|
kernel_addr_r = genimg_get_kernel_addr(kernel_addr);
|
||||||
buf = map_sysmem(kernel_addr_r, 0);
|
buf = map_sysmem(kernel_addr_r, 0);
|
||||||
|
|
||||||
if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT)
|
if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) {
|
||||||
bootm_argv[3] = env_get("fdtcontroladdr");
|
if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) {
|
||||||
|
if (strcmp("-", label->fdt))
|
||||||
|
bootm_argv[3] = env_get("fdtcontroladdr");
|
||||||
|
} else {
|
||||||
|
bootm_argv[3] = env_get("fdtcontroladdr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bootm_argv[3]) {
|
if (bootm_argv[3]) {
|
||||||
if (!bootm_argv[2])
|
if (!bootm_argv[2])
|
||||||
|
|
10
cmd/Kconfig
10
cmd/Kconfig
|
@ -740,6 +740,7 @@ config CRC32_VERIFY
|
||||||
|
|
||||||
config CMD_EEPROM
|
config CMD_EEPROM
|
||||||
bool "eeprom - EEPROM subsystem"
|
bool "eeprom - EEPROM subsystem"
|
||||||
|
depends on DM_I2C || SYS_I2C_LEGACY
|
||||||
help
|
help
|
||||||
(deprecated, needs conversion to driver model)
|
(deprecated, needs conversion to driver model)
|
||||||
Provides commands to read and write EEPROM (Electrically Erasable
|
Provides commands to read and write EEPROM (Electrically Erasable
|
||||||
|
@ -2750,15 +2751,6 @@ config MTDPARTS_DEFAULT
|
||||||
Defines a default MTD partitioning scheme in the Linux MTD command
|
Defines a default MTD partitioning scheme in the Linux MTD command
|
||||||
line partitions format
|
line partitions format
|
||||||
|
|
||||||
config CMD_REISER
|
|
||||||
bool "reiser - Access to reiserfs filesystems"
|
|
||||||
help
|
|
||||||
This provides two commands which operate on a resierfs filesystem,
|
|
||||||
commonly used some years ago:
|
|
||||||
|
|
||||||
reiserls - list files
|
|
||||||
reiserload - load a file
|
|
||||||
|
|
||||||
config CMD_YAFFS2
|
config CMD_YAFFS2
|
||||||
bool "yaffs2 - Access of YAFFS2 filesystem"
|
bool "yaffs2 - Access of YAFFS2 filesystem"
|
||||||
depends on YAFFS2
|
depends on YAFFS2
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
|
|
||||||
static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
|
171
cmd/reiser.c
171
cmd/reiser.c
|
@ -1,171 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* (C) Copyright 2003 - 2004
|
|
||||||
* Sysgo Real-Time Solutions, AG <www.elinos.com>
|
|
||||||
* Pavel Bartusek <pba@sysgo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reiserfs support
|
|
||||||
*/
|
|
||||||
#include <common.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <command.h>
|
|
||||||
#include <env.h>
|
|
||||||
#include <image.h>
|
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <asm/byteorder.h>
|
|
||||||
#include <reiserfs.h>
|
|
||||||
#include <part.h>
|
|
||||||
|
|
||||||
#if !CONFIG_IS_ENABLED(DOS_PARTITION)
|
|
||||||
#error DOS partition support must be selected
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define REISER_DEBUG */
|
|
||||||
|
|
||||||
#ifdef REISER_DEBUG
|
|
||||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
|
||||||
#else
|
|
||||||
#define PRINTF(fmt,args...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int do_reiserls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|
||||||
{
|
|
||||||
char *filename = "/";
|
|
||||||
int dev, part;
|
|
||||||
struct blk_desc *dev_desc = NULL;
|
|
||||||
struct disk_partition info;
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
return CMD_RET_USAGE;
|
|
||||||
|
|
||||||
part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
|
|
||||||
if (part < 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (argc == 4) {
|
|
||||||
filename = argv[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = dev_desc->devnum;
|
|
||||||
PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
|
|
||||||
|
|
||||||
reiserfs_set_blk_dev(dev_desc, &info);
|
|
||||||
|
|
||||||
if (!reiserfs_mount(info.size)) {
|
|
||||||
printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reiserfs_ls (filename)) {
|
|
||||||
printf ("** Error reiserfs_ls() **\n");
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
U_BOOT_CMD(
|
|
||||||
reiserls, 4, 1, do_reiserls,
|
|
||||||
"list files in a directory (default /)",
|
|
||||||
"<interface> <dev[:part]> [directory]\n"
|
|
||||||
" - list files from 'dev' on 'interface' in a 'directory'"
|
|
||||||
);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Reiserfs boot command intepreter. Derived from diskboot
|
|
||||||
*/
|
|
||||||
int do_reiserload(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|
||||||
{
|
|
||||||
char *filename = NULL;
|
|
||||||
int dev, part;
|
|
||||||
ulong addr = 0, filelen;
|
|
||||||
struct disk_partition info;
|
|
||||||
struct blk_desc *dev_desc = NULL;
|
|
||||||
unsigned long count;
|
|
||||||
char *addr_str;
|
|
||||||
|
|
||||||
switch (argc) {
|
|
||||||
case 3:
|
|
||||||
addr_str = env_get("loadaddr");
|
|
||||||
if (addr_str != NULL) {
|
|
||||||
addr = hextoul(addr_str, NULL);
|
|
||||||
} else {
|
|
||||||
addr = CONFIG_SYS_LOAD_ADDR;
|
|
||||||
}
|
|
||||||
filename = env_get("bootfile");
|
|
||||||
count = 0;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
addr = hextoul(argv[3], NULL);
|
|
||||||
filename = env_get("bootfile");
|
|
||||||
count = 0;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
addr = hextoul(argv[3], NULL);
|
|
||||||
filename = argv[4];
|
|
||||||
count = 0;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
addr = hextoul(argv[3], NULL);
|
|
||||||
filename = argv[4];
|
|
||||||
count = hextoul(argv[5], NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CMD_RET_USAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filename) {
|
|
||||||
puts ("\n** No boot file defined **\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
|
|
||||||
if (part < 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
dev = dev_desc->devnum;
|
|
||||||
|
|
||||||
printf("Loading file \"%s\" from %s device %d%c%c\n",
|
|
||||||
filename, argv[1], dev,
|
|
||||||
part ? ':' : ' ', part ? part + '0' : ' ');
|
|
||||||
|
|
||||||
reiserfs_set_blk_dev(dev_desc, &info);
|
|
||||||
|
|
||||||
if (!reiserfs_mount(info.size)) {
|
|
||||||
printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
filelen = reiserfs_open(filename);
|
|
||||||
if (filelen < 0) {
|
|
||||||
printf("** File not found %s **\n", filename);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((count < filelen) && (count != 0)) {
|
|
||||||
filelen = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reiserfs_read((char *)addr, filelen) != filelen) {
|
|
||||||
printf("\n** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loading ok, update default load address */
|
|
||||||
image_load_addr = addr;
|
|
||||||
|
|
||||||
printf ("\n%ld bytes read\n", filelen);
|
|
||||||
env_set_hex("filesize", filelen);
|
|
||||||
|
|
||||||
return filelen;
|
|
||||||
}
|
|
||||||
|
|
||||||
U_BOOT_CMD(
|
|
||||||
reiserload, 6, 0, do_reiserload,
|
|
||||||
"load binary file from a Reiser filesystem",
|
|
||||||
"<interface> <dev[:part]> [addr] [filename] [bytes]\n"
|
|
||||||
" - load binary file 'filename' from 'dev' on 'interface'\n"
|
|
||||||
" to address 'addr' from dos filesystem"
|
|
||||||
);
|
|
|
@ -5,7 +5,6 @@
|
||||||
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
|
|
||||||
static int do_compressed(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_compressed(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
* Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
* Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
|
|
||||||
static int do_sigsegv(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_sigsegv(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
|
|
@ -216,14 +216,12 @@ int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size,
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (loop == 0) {
|
if (loop == 0) {
|
||||||
debug("%s: No match\n", data);
|
debug("%s: No match\n", data);
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
debug("## MATCH ## %s\n", data);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("## MATCH ## %s\n", data);
|
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -540,7 +538,8 @@ U_BOOT_CMD(
|
||||||
" - For each substring matching the regular expression <r> in the\n"
|
" - For each substring matching the regular expression <r> in the\n"
|
||||||
" string <t>, substitute the string <s>. The result is\n"
|
" string <t>, substitute the string <s>. The result is\n"
|
||||||
" assigned to <name>. If <t> is not supplied, use the old\n"
|
" assigned to <name>. If <t> is not supplied, use the old\n"
|
||||||
" value of <name>\n"
|
" value of <name>. If no substring matching <r> is found in <t>,\n"
|
||||||
|
" assign <t> to <name>.\n"
|
||||||
"setexpr name sub r s [t]\n"
|
"setexpr name sub r s [t]\n"
|
||||||
" - Just like gsub(), but replace only the first matching substring"
|
" - Just like gsub(), but replace only the first matching substring"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
* Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
|
|
||||||
static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
|
|
@ -282,7 +282,9 @@ static int init_func_i2c(void)
|
||||||
|
|
||||||
static int setup_mon_len(void)
|
static int setup_mon_len(void)
|
||||||
{
|
{
|
||||||
#if defined(__ARM__) || defined(__MICROBLAZE__)
|
#if defined(CONFIG_ARCH_NEXELL)
|
||||||
|
gd->mon_len = (ulong)__bss_end - (ulong)__image_copy_start;
|
||||||
|
#elif defined(__ARM__) || defined(__MICROBLAZE__)
|
||||||
gd->mon_len = (ulong)__bss_end - (ulong)_start;
|
gd->mon_len = (ulong)__bss_end - (ulong)_start;
|
||||||
#elif defined(CONFIG_SANDBOX) && !defined(__riscv)
|
#elif defined(CONFIG_SANDBOX) && !defined(__riscv)
|
||||||
gd->mon_len = (ulong)_end - (ulong)_init;
|
gd->mon_len = (ulong)_end - (ulong)_init;
|
||||||
|
|
|
@ -428,6 +428,11 @@ int log_device_set_enable(struct log_driver *drv, bool enable)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_fixup_for_gd_move(struct global_data *new_gd)
|
||||||
|
{
|
||||||
|
new_gd->log_head.prev->next = &new_gd->log_head;
|
||||||
|
}
|
||||||
|
|
||||||
int log_init(void)
|
int log_init(void)
|
||||||
{
|
{
|
||||||
struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);
|
struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);
|
||||||
|
|
|
@ -909,6 +909,9 @@ ulong spl_relocate_stack_gd(void)
|
||||||
#if CONFIG_IS_ENABLED(DM)
|
#if CONFIG_IS_ENABLED(DM)
|
||||||
dm_fixup_for_gd_move(new_gd);
|
dm_fixup_for_gd_move(new_gd);
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_IS_ENABLED(LOG)
|
||||||
|
log_fixup_for_gd_move(new_gd);
|
||||||
|
#endif
|
||||||
#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
|
#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
|
||||||
gd = new_gd;
|
gd = new_gd;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,7 +53,6 @@ CONFIG_CMD_JFFS2=y
|
||||||
CONFIG_CMD_MTDPARTS=y
|
CONFIG_CMD_MTDPARTS=y
|
||||||
CONFIG_MTDIDS_DEFAULT="nand0=atmel_nand"
|
CONFIG_MTDIDS_DEFAULT="nand0=atmel_nand"
|
||||||
CONFIG_MTDPARTS_DEFAULT="mtdparts=atmel_nand:-(root)"
|
CONFIG_MTDPARTS_DEFAULT="mtdparts=atmel_nand:-(root)"
|
||||||
CONFIG_CMD_REISER=y
|
|
||||||
CONFIG_CMD_UBI=y
|
CONFIG_CMD_UBI=y
|
||||||
CONFIG_OF_CONTROL=y
|
CONFIG_OF_CONTROL=y
|
||||||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||||
|
|
|
@ -531,6 +531,10 @@ Then the iterator is set up to according to the parameters given:
|
||||||
`BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
|
`BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
|
||||||
processes just the children of the media device. Hunters are used, in this
|
processes just the children of the media device. Hunters are used, in this
|
||||||
example just the "mmc" hunter.
|
example just the "mmc" hunter.
|
||||||
|
- If `label` indicates a particular partition in a particular media device
|
||||||
|
(e.g. "mmc1:3") then `BOOTFLOWIF_SINGLE_PARTITION` is set. In this case,
|
||||||
|
only a single partition within a bootdev is processed. Hunters are used, in
|
||||||
|
this example just the "mmc" hunter.
|
||||||
- If `label` indicates a media uclass (e.g. "mmc") then
|
- If `label` indicates a media uclass (e.g. "mmc") then
|
||||||
`BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
|
`BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
|
||||||
are used. Hunters are used, in this example just the "mmc" hunter
|
are used. Hunters are used, in this example just the "mmc" hunter
|
||||||
|
|
|
@ -81,6 +81,12 @@ as specified at `Boot Loader Specification`_:
|
||||||
* Does not document the fdtdir option, which automatically selects the DTB to
|
* Does not document the fdtdir option, which automatically selects the DTB to
|
||||||
pass to the kernel.
|
pass to the kernel.
|
||||||
|
|
||||||
|
* If no fdt/fdtdir is provided, the U-Boot will pass its own currently used
|
||||||
|
device tree.
|
||||||
|
|
||||||
|
* If ``-`` is passed as fdt argument and ``CONFIG_SUPPORT_PASSING_ATAGS`` is
|
||||||
|
enabled, then no device tree will be used (legacy booting / pre-dtb kernel).
|
||||||
|
|
||||||
See also doc/README.pxe under 'pxe file format'.
|
See also doc/README.pxe under 'pxe file format'.
|
||||||
|
|
||||||
One example extlinux.conf generated by the Fedora installer is::
|
One example extlinux.conf generated by the Fedora installer is::
|
||||||
|
|
|
@ -39,6 +39,7 @@ setexpr name gsub <r> <s> [<t>]
|
||||||
string <t>, substitute the string <s>.
|
string <t>, substitute the string <s>.
|
||||||
The result is assigned to <name>.
|
The result is assigned to <name>.
|
||||||
If <t> is not supplied, use the old value of <name>.
|
If <t> is not supplied, use the old value of <name>.
|
||||||
|
If no substring matching <r> is found in <t>, assign <t> to <name>.
|
||||||
|
|
||||||
setexpr name sub <r> <s> [<t>]
|
setexpr name sub <r> <s> [<t>]
|
||||||
Just like gsub(), but replace only the first matching substring
|
Just like gsub(), but replace only the first matching substring
|
||||||
|
|
|
@ -23,7 +23,7 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index)
|
||||||
{
|
{
|
||||||
#if CONFIG_IS_ENABLED(OF_REAL)
|
#if CONFIG_IS_ENABLED(OF_REAL)
|
||||||
int offset = dev_of_offset(dev);
|
int offset = dev_of_offset(dev);
|
||||||
int parent = dev_of_offset(dev->parent);
|
int parent = fdt_parent_offset(gd->fdt_blob, offset);
|
||||||
fdt_addr_t addr;
|
fdt_addr_t addr;
|
||||||
|
|
||||||
if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
|
if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
|
||||||
|
|
|
@ -128,6 +128,8 @@ struct macb_device {
|
||||||
unsigned long dummy_desc_dma;
|
unsigned long dummy_desc_dma;
|
||||||
|
|
||||||
const struct device *dev;
|
const struct device *dev;
|
||||||
|
unsigned int duplex;
|
||||||
|
unsigned int speed;
|
||||||
unsigned short phy_addr;
|
unsigned short phy_addr;
|
||||||
struct mii_dev *bus;
|
struct mii_dev *bus;
|
||||||
#ifdef CONFIG_PHYLIB
|
#ifdef CONFIG_PHYLIB
|
||||||
|
@ -178,6 +180,12 @@ static int gem_is_gigabit_capable(struct macb_device *macb)
|
||||||
return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
|
return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is the port a fixed link */
|
||||||
|
static int macb_port_is_fixed_link(struct macb_device *macb)
|
||||||
|
{
|
||||||
|
return macb->phy_addr > PHY_MAX_ADDR;
|
||||||
|
}
|
||||||
|
|
||||||
static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
|
static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
|
||||||
u16 value)
|
u16 value)
|
||||||
{
|
{
|
||||||
|
@ -666,97 +674,109 @@ static int macb_phy_init(struct udevice *dev, const char *name)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
arch_get_mdio_control(name);
|
arch_get_mdio_control(name);
|
||||||
/* Auto-detect phy_addr */
|
/* If port is not fixed -> setup PHY */
|
||||||
ret = macb_phy_find(macb, name);
|
if (!macb_port_is_fixed_link(macb)) {
|
||||||
if (ret)
|
/* Auto-detect phy_addr */
|
||||||
return ret;
|
ret = macb_phy_find(macb, name);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Check if the PHY is up to snuff... */
|
/* Check if the PHY is up to snuff... */
|
||||||
phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
|
phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
|
||||||
if (phy_id == 0xffff) {
|
if (phy_id == 0xffff) {
|
||||||
printf("%s: No PHY present\n", name);
|
printf("%s: No PHY present\n", name);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PHYLIB
|
#ifdef CONFIG_PHYLIB
|
||||||
macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
|
macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
|
||||||
macb->phy_interface);
|
macb->phy_interface);
|
||||||
if (!macb->phydev) {
|
if (!macb->phydev) {
|
||||||
printf("phy_connect failed\n");
|
printf("phy_connect failed\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
phy_config(macb->phydev);
|
phy_config(macb->phydev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
|
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
|
||||||
if (!(status & BMSR_LSTATUS)) {
|
if (!(status & BMSR_LSTATUS)) {
|
||||||
/* Try to re-negotiate if we don't have link already. */
|
/* Try to re-negotiate if we don't have link already. */
|
||||||
macb_phy_reset(macb, name);
|
macb_phy_reset(macb, name);
|
||||||
|
|
||||||
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
|
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
|
||||||
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
|
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
|
||||||
if (status & BMSR_LSTATUS) {
|
if (status & BMSR_LSTATUS) {
|
||||||
/*
|
/*
|
||||||
* Delay a bit after the link is established,
|
* Delay a bit after the link is established,
|
||||||
* so that the next xfer does not fail
|
* so that the next xfer does not fail
|
||||||
*/
|
*/
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
udelay(100);
|
||||||
}
|
}
|
||||||
udelay(100);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!(status & BMSR_LSTATUS)) {
|
if (!(status & BMSR_LSTATUS)) {
|
||||||
printf("%s: link down (status: 0x%04x)\n",
|
printf("%s: link down (status: 0x%04x)\n",
|
||||||
name, status);
|
name, status);
|
||||||
return -ENETDOWN;
|
return -ENETDOWN;
|
||||||
}
|
|
||||||
|
|
||||||
/* First check for GMAC and that it is GiB capable */
|
|
||||||
if (gem_is_gigabit_capable(macb)) {
|
|
||||||
lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
|
|
||||||
|
|
||||||
if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
|
|
||||||
LPA_1000XHALF)) {
|
|
||||||
duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
|
|
||||||
1 : 0);
|
|
||||||
|
|
||||||
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
|
|
||||||
name,
|
|
||||||
duplex ? "full" : "half",
|
|
||||||
lpa);
|
|
||||||
|
|
||||||
ncfgr = macb_readl(macb, NCFGR);
|
|
||||||
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
|
||||||
ncfgr |= GEM_BIT(GBE);
|
|
||||||
|
|
||||||
if (duplex)
|
|
||||||
ncfgr |= MACB_BIT(FD);
|
|
||||||
|
|
||||||
macb_writel(macb, NCFGR, ncfgr);
|
|
||||||
|
|
||||||
ret = macb_linkspd_cb(dev, _1000BASET);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* fall back for EMAC checking */
|
/* First check for GMAC and that it is GiB capable */
|
||||||
adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
|
if (gem_is_gigabit_capable(macb)) {
|
||||||
lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
|
lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
|
||||||
media = mii_nway_result(lpa & adv);
|
|
||||||
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
|
||||||
? 1 : 0);
|
LPA_1000XHALF)) {
|
||||||
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
|
||||||
printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
|
1 : 0);
|
||||||
name,
|
|
||||||
speed ? "100" : "10",
|
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
|
||||||
duplex ? "full" : "half",
|
name,
|
||||||
lpa);
|
duplex ? "full" : "half",
|
||||||
|
lpa);
|
||||||
|
|
||||||
|
ncfgr = macb_readl(macb, NCFGR);
|
||||||
|
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
||||||
|
ncfgr |= GEM_BIT(GBE);
|
||||||
|
|
||||||
|
if (duplex)
|
||||||
|
ncfgr |= MACB_BIT(FD);
|
||||||
|
|
||||||
|
macb_writel(macb, NCFGR, ncfgr);
|
||||||
|
|
||||||
|
ret = macb_linkspd_cb(dev, _1000BASET);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall back for EMAC checking */
|
||||||
|
adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
|
||||||
|
lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
|
||||||
|
media = mii_nway_result(lpa & adv);
|
||||||
|
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
||||||
|
? 1 : 0);
|
||||||
|
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
||||||
|
printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
|
||||||
|
name,
|
||||||
|
speed ? "100" : "10",
|
||||||
|
duplex ? "full" : "half",
|
||||||
|
lpa);
|
||||||
|
} else {
|
||||||
|
/* if macb port is a fixed link */
|
||||||
|
/* TODO : manage gigabit capable processors */
|
||||||
|
speed = macb->speed;
|
||||||
|
duplex = macb->duplex;
|
||||||
|
printf("%s: link up, %sMbps %s-duplex\n",
|
||||||
|
name,
|
||||||
|
speed ? "100" : "10",
|
||||||
|
duplex ? "full" : "half");
|
||||||
|
}
|
||||||
|
|
||||||
ncfgr = macb_readl(macb, NCFGR);
|
ncfgr = macb_readl(macb, NCFGR);
|
||||||
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
|
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
|
||||||
|
@ -1276,6 +1296,28 @@ int __weak macb_late_eth_of_to_plat(struct udevice *dev)
|
||||||
static int macb_eth_of_to_plat(struct udevice *dev)
|
static int macb_eth_of_to_plat(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||||
|
struct macb_device *macb = dev_get_priv(dev);
|
||||||
|
void *blob = (void *)gd->fdt_blob;
|
||||||
|
int node = dev_of_offset(dev);
|
||||||
|
int fl_node, speed_fdt;
|
||||||
|
|
||||||
|
/* fetch 'fixed-link' property */
|
||||||
|
fl_node = fdt_subnode_offset(blob, node, "fixed-link");
|
||||||
|
if (fl_node >= 0) {
|
||||||
|
/* set phy_addr to invalid value for fixed link */
|
||||||
|
macb->phy_addr = PHY_MAX_ADDR + 1;
|
||||||
|
macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
|
||||||
|
speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0);
|
||||||
|
if (speed_fdt == 100) {
|
||||||
|
macb->speed = 1;
|
||||||
|
} else if (speed_fdt == 10) {
|
||||||
|
macb->speed = 0;
|
||||||
|
} else {
|
||||||
|
printf("%s: The given speed %d of ethernet in the DT is not supported\n",
|
||||||
|
__func__, speed_fdt);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pdata->iobase = (uintptr_t)dev_remap_addr(dev);
|
pdata->iobase = (uintptr_t)dev_remap_addr(dev);
|
||||||
if (!pdata->iobase)
|
if (!pdata->iobase)
|
||||||
|
|
|
@ -137,6 +137,7 @@ struct mtk_eth_priv {
|
||||||
int force_mode;
|
int force_mode;
|
||||||
int speed;
|
int speed;
|
||||||
int duplex;
|
int duplex;
|
||||||
|
int mdc;
|
||||||
bool pn_swap;
|
bool pn_swap;
|
||||||
|
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
|
@ -1245,7 +1246,8 @@ static int mtk_phy_start(struct mtk_eth_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!priv->force_mode) {
|
if (!priv->force_mode) {
|
||||||
if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
|
if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
|
||||||
|
priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
|
||||||
mtk_xphy_link_adjust(priv);
|
mtk_xphy_link_adjust(priv);
|
||||||
else
|
else
|
||||||
mtk_phy_link_adjust(priv);
|
mtk_phy_link_adjust(priv);
|
||||||
|
@ -1515,7 +1517,7 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
|
||||||
|
|
||||||
static void mtk_xmac_init(struct mtk_eth_priv *priv)
|
static void mtk_xmac_init(struct mtk_eth_priv *priv)
|
||||||
{
|
{
|
||||||
u32 sts;
|
u32 force_link = 0;
|
||||||
|
|
||||||
switch (priv->phy_interface) {
|
switch (priv->phy_interface) {
|
||||||
case PHY_INTERFACE_MODE_USXGMII:
|
case PHY_INTERFACE_MODE_USXGMII:
|
||||||
|
@ -1530,15 +1532,19 @@ static void mtk_xmac_init(struct mtk_eth_priv *priv)
|
||||||
SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id),
|
SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id),
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (priv->gmac_id == 1) {
|
if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII &&
|
||||||
|
priv->gmac_id == 1) {
|
||||||
mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX,
|
mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX,
|
||||||
NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL);
|
NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL);
|
||||||
} else if (priv->gmac_id == 2) {
|
|
||||||
sts = mtk_gmac_read(priv, XGMAC_STS(priv->gmac_id));
|
|
||||||
sts |= XGMAC_FORCE_LINK;
|
|
||||||
mtk_gmac_write(priv, XGMAC_STS(priv->gmac_id), sts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->phy_interface == PHY_INTERFACE_MODE_XGMII ||
|
||||||
|
priv->gmac_id == 2)
|
||||||
|
force_link = XGMAC_FORCE_LINK(priv->gmac_id);
|
||||||
|
|
||||||
|
mtk_gmac_rmw(priv, XGMAC_STS(priv->gmac_id),
|
||||||
|
XGMAC_FORCE_LINK(priv->gmac_id), force_link);
|
||||||
|
|
||||||
/* Force GMAC link down */
|
/* Force GMAC link down */
|
||||||
mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE);
|
mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE);
|
||||||
}
|
}
|
||||||
|
@ -1607,6 +1613,26 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
|
||||||
mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
|
mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mtk_eth_mdc_init(struct mtk_eth_priv *priv)
|
||||||
|
{
|
||||||
|
u32 divider;
|
||||||
|
|
||||||
|
if (priv->mdc == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER);
|
||||||
|
|
||||||
|
/* Configure MDC turbo mode */
|
||||||
|
if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
|
||||||
|
mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO);
|
||||||
|
else
|
||||||
|
mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO);
|
||||||
|
|
||||||
|
/* Configure MDC divider */
|
||||||
|
mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG,
|
||||||
|
FIELD_PREP(PHY_MDC_CFG, divider));
|
||||||
|
}
|
||||||
|
|
||||||
static int mtk_eth_start(struct udevice *dev)
|
static int mtk_eth_start(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct mtk_eth_priv *priv = dev_get_priv(dev);
|
struct mtk_eth_priv *priv = dev_get_priv(dev);
|
||||||
|
@ -1803,8 +1829,12 @@ static int mtk_eth_probe(struct udevice *dev)
|
||||||
noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
|
noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
|
||||||
ARCH_DMA_MINALIGN);
|
ARCH_DMA_MINALIGN);
|
||||||
|
|
||||||
|
/* Set MDC divider */
|
||||||
|
mtk_eth_mdc_init(priv);
|
||||||
|
|
||||||
/* Set MAC mode */
|
/* Set MAC mode */
|
||||||
if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
|
if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
|
||||||
|
priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
|
||||||
mtk_xmac_init(priv);
|
mtk_xmac_init(priv);
|
||||||
else
|
else
|
||||||
mtk_mac_init(priv);
|
mtk_mac_init(priv);
|
||||||
|
@ -1881,6 +1911,17 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
|
||||||
|
|
||||||
priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
|
priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
|
||||||
|
|
||||||
|
priv->mdc = 0;
|
||||||
|
subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio");
|
||||||
|
if (ofnode_valid(subnode)) {
|
||||||
|
priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000);
|
||||||
|
if (priv->mdc > MDC_MAX_FREQ ||
|
||||||
|
priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) {
|
||||||
|
printf("error: MDIO clock frequency out of range\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Interface mode is required */
|
/* Interface mode is required */
|
||||||
pdata->phy_interface = dev_read_phy_mode(dev);
|
pdata->phy_interface = dev_read_phy_mode(dev);
|
||||||
priv->phy_interface = pdata->phy_interface;
|
priv->phy_interface = pdata->phy_interface;
|
||||||
|
|
|
@ -180,6 +180,12 @@ enum mkt_eth_capabilities {
|
||||||
|
|
||||||
/* GMAC Registers */
|
/* GMAC Registers */
|
||||||
|
|
||||||
|
#define GMAC_PPSC_REG 0x0000
|
||||||
|
#define PHY_MDC_CFG GENMASK(29, 24)
|
||||||
|
#define MDC_TURBO BIT(20)
|
||||||
|
#define MDC_MAX_FREQ 25000000
|
||||||
|
#define MDC_MAX_DIVIDER 63
|
||||||
|
|
||||||
#define GMAC_PIAC_REG 0x0004
|
#define GMAC_PIAC_REG 0x0004
|
||||||
#define PHY_ACS_ST BIT(31)
|
#define PHY_ACS_ST BIT(31)
|
||||||
#define MDIO_REG_ADDR_S 25
|
#define MDIO_REG_ADDR_S 25
|
||||||
|
@ -197,6 +203,7 @@ enum mkt_eth_capabilities {
|
||||||
#define P1_XGMAC_FORCE_LINK BIT(15)
|
#define P1_XGMAC_FORCE_LINK BIT(15)
|
||||||
|
|
||||||
#define GMAC_MAC_MISC_REG 0x0010
|
#define GMAC_MAC_MISC_REG 0x0010
|
||||||
|
#define MISC_MDC_TURBO BIT(4)
|
||||||
|
|
||||||
#define GMAC_GSW_CFG_REG 0x0080
|
#define GMAC_GSW_CFG_REG 0x0080
|
||||||
#define GSWTX_IPG_M 0xF0000
|
#define GSWTX_IPG_M 0xF0000
|
||||||
|
@ -261,7 +268,7 @@ enum mkt_eth_capabilities {
|
||||||
|
|
||||||
/* XGMAC Status Registers */
|
/* XGMAC Status Registers */
|
||||||
#define XGMAC_STS(x) (((x) == 2) ? 0x001C : 0x000C)
|
#define XGMAC_STS(x) (((x) == 2) ? 0x001C : 0x000C)
|
||||||
#define XGMAC_FORCE_LINK BIT(15)
|
#define XGMAC_FORCE_LINK(x) (((x) == 1) ? BIT(31) : BIT(15))
|
||||||
|
|
||||||
/* XGMAC Registers */
|
/* XGMAC Registers */
|
||||||
#define XGMAC_PORT_MCR(x) (0x2000 + (((x) - 1) * 0x1000))
|
#define XGMAC_PORT_MCR(x) (0x2000 + (((x) - 1) * 0x1000))
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <pci.h>
|
#include <pci.h>
|
||||||
#include <asm/global_data.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
@ -133,18 +133,17 @@ static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||||
static int pci_generic_ecam_of_to_plat(struct udevice *dev)
|
static int pci_generic_ecam_of_to_plat(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct generic_ecam_pcie *pcie = dev_get_priv(dev);
|
struct generic_ecam_pcie *pcie = dev_get_priv(dev);
|
||||||
struct fdt_resource reg_res;
|
ofnode node = dev_ofnode(dev);
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
struct resource reg_res;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
|
err = ofnode_read_resource(node, 0, ®_res);
|
||||||
0, ®_res);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("\"reg\" resource not found\n");
|
pr_err("\"reg\" resource not found\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcie->size = fdt_resource_size(®_res);
|
pcie->size = resource_size(®_res);
|
||||||
pcie->cfg_base = map_physmem(reg_res.start, pcie->size, MAP_NOCACHE);
|
pcie->cfg_base = map_physmem(reg_res.start, pcie->size, MAP_NOCACHE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -267,6 +267,14 @@ static struct aspeed_sig_desc fmcquad_link[] = {
|
||||||
{ 0x438, GENMASK(5, 4), 0 },
|
{ 0x438, GENMASK(5, 4), 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc siopbi_link[] = {
|
||||||
|
{ 0x418, BIT(6), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc siopbo_link[] = {
|
||||||
|
{ 0x418, BIT(5), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
static struct aspeed_sig_desc spi1_link[] = {
|
static struct aspeed_sig_desc spi1_link[] = {
|
||||||
{ 0x438, GENMASK(13, 11), 0 },
|
{ 0x438, GENMASK(13, 11), 0 },
|
||||||
};
|
};
|
||||||
|
@ -303,6 +311,22 @@ static struct aspeed_sig_desc spi2quad_link[] = {
|
||||||
{ 0x434, GENMASK(31, 30), 0 },
|
{ 0x434, GENMASK(31, 30), 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc thru0_link[] = {
|
||||||
|
{ 0x4bc, GENMASK(25, 24), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc thru1_link[] = {
|
||||||
|
{ 0x4bc, GENMASK(27, 26), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc thru2_link[] = {
|
||||||
|
{ 0x4bc, GENMASK(29, 28), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aspeed_sig_desc thru3_link[] = {
|
||||||
|
{ 0x4bc, GENMASK(31, 30), 0 },
|
||||||
|
};
|
||||||
|
|
||||||
static struct aspeed_sig_desc fsi1[] = {
|
static struct aspeed_sig_desc fsi1[] = {
|
||||||
{ 0xd48, GENMASK(21, 20), 0 },
|
{ 0xd48, GENMASK(21, 20), 0 },
|
||||||
};
|
};
|
||||||
|
@ -458,6 +482,8 @@ static const struct aspeed_group_config ast2600_groups[] = {
|
||||||
{ "EMMC", ARRAY_SIZE(emmc_link), emmc_link },
|
{ "EMMC", ARRAY_SIZE(emmc_link), emmc_link },
|
||||||
{ "EMMCG8", ARRAY_SIZE(emmcg8_link), emmcg8_link },
|
{ "EMMCG8", ARRAY_SIZE(emmcg8_link), emmcg8_link },
|
||||||
{ "FMCQUAD", ARRAY_SIZE(fmcquad_link), fmcquad_link },
|
{ "FMCQUAD", ARRAY_SIZE(fmcquad_link), fmcquad_link },
|
||||||
|
{ "SIOPBI", ARRAY_SIZE(siopbi_link), siopbi_link },
|
||||||
|
{ "SIOPBO", ARRAY_SIZE(siopbo_link), siopbo_link },
|
||||||
{ "SPI1", ARRAY_SIZE(spi1_link), spi1_link },
|
{ "SPI1", ARRAY_SIZE(spi1_link), spi1_link },
|
||||||
{ "SPI1ABR", ARRAY_SIZE(spi1abr_link), spi1abr_link },
|
{ "SPI1ABR", ARRAY_SIZE(spi1abr_link), spi1abr_link },
|
||||||
{ "SPI1CS1", ARRAY_SIZE(spi1cs1_link), spi1cs1_link },
|
{ "SPI1CS1", ARRAY_SIZE(spi1cs1_link), spi1cs1_link },
|
||||||
|
@ -467,6 +493,10 @@ static const struct aspeed_group_config ast2600_groups[] = {
|
||||||
{ "SPI2CS1", ARRAY_SIZE(spi2cs1_link), spi2cs1_link },
|
{ "SPI2CS1", ARRAY_SIZE(spi2cs1_link), spi2cs1_link },
|
||||||
{ "SPI2CS2", ARRAY_SIZE(spi2cs2_link), spi2cs2_link },
|
{ "SPI2CS2", ARRAY_SIZE(spi2cs2_link), spi2cs2_link },
|
||||||
{ "SPI2QUAD", ARRAY_SIZE(spi2quad_link), spi2quad_link },
|
{ "SPI2QUAD", ARRAY_SIZE(spi2quad_link), spi2quad_link },
|
||||||
|
{ "THRU0", ARRAY_SIZE(thru0_link), thru0_link },
|
||||||
|
{ "THRU1", ARRAY_SIZE(thru1_link), thru1_link },
|
||||||
|
{ "THRU2", ARRAY_SIZE(thru2_link), thru2_link },
|
||||||
|
{ "THRU3", ARRAY_SIZE(thru3_link), thru3_link },
|
||||||
{ "I2C1", ARRAY_SIZE(i2c1_link), i2c1_link },
|
{ "I2C1", ARRAY_SIZE(i2c1_link), i2c1_link },
|
||||||
{ "I2C2", ARRAY_SIZE(i2c2_link), i2c2_link },
|
{ "I2C2", ARRAY_SIZE(i2c2_link), i2c2_link },
|
||||||
{ "I2C3", ARRAY_SIZE(i2c3_link), i2c3_link },
|
{ "I2C3", ARRAY_SIZE(i2c3_link), i2c3_link },
|
||||||
|
|
|
@ -100,6 +100,22 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ofnode_pre_reloc_recursive(ofnode parent)
|
||||||
|
{
|
||||||
|
ofnode child;
|
||||||
|
|
||||||
|
if (ofnode_pre_reloc(parent))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(PINCONF_RECURSIVE)) {
|
||||||
|
ofnode_for_each_subnode(child, parent)
|
||||||
|
if (ofnode_pre_reloc_recursive(child))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pinconfig_post_bind() - post binding for PINCONFIG uclass
|
* pinconfig_post_bind() - post binding for PINCONFIG uclass
|
||||||
* Recursively bind its children as pinconfig devices.
|
* Recursively bind its children as pinconfig devices.
|
||||||
|
@ -119,7 +135,7 @@ static int pinconfig_post_bind(struct udevice *dev)
|
||||||
|
|
||||||
dev_for_each_subnode(node, dev) {
|
dev_for_each_subnode(node, dev) {
|
||||||
if (pre_reloc_only &&
|
if (pre_reloc_only &&
|
||||||
!ofnode_pre_reloc(node))
|
!ofnode_pre_reloc_recursive(node))
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
* If this node has "compatible" property, this is not
|
* If this node has "compatible" property, this is not
|
||||||
|
|
|
@ -9,11 +9,10 @@
|
||||||
|
|
||||||
#define LOG_CATEGORY UCLASS_RNG
|
#define LOG_CATEGORY UCLASS_RNG
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
#define DRIVER_NAME "arm-rndr"
|
#define DRIVER_NAME "arm-rndr"
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
* Driver for Raspberry Pi hardware random number generator
|
* Driver for Raspberry Pi hardware random number generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#define usleep_range(a, b) udelay((b))
|
#define usleep_range(a, b) udelay((b))
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
* Driver for Amlogic hardware random number generator
|
* Driver for Amlogic hardware random number generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
|
|
@ -9,12 +9,11 @@
|
||||||
* Based on Linux driver
|
* Based on Linux driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <linux/bitops.h>
|
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
/* Device specific register offsets */
|
/* Device specific register offsets */
|
||||||
#define PRNG_DATA_OUT 0x0000
|
#define PRNG_DATA_OUT 0x0000
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* Copyright (c) 2022 Nuvoton Technology Corp.
|
* Copyright (c) 2022 Nuvoton Technology Corp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
*/
|
*/
|
||||||
#define LOG_CATEGORY UCLASS_RNG
|
#define LOG_CATEGORY UCLASS_RNG
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
|
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
#include <tee.h>
|
#include <tee.h>
|
||||||
#include <dm/device.h>
|
#include <dm/device.h>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#define LOG_CATEGORY UCLASS_RNG
|
#define LOG_CATEGORY UCLASS_RNG
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
|
* Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dm.h>
|
||||||
|
#include <rng.h>
|
||||||
#include <asm/arch-rockchip/hardware.h>
|
#include <asm/arch-rockchip/hardware.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <rng.h>
|
|
||||||
|
|
||||||
#define RK_HW_RNG_MAX 32
|
#define RK_HW_RNG_MAX 32
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
* Copyright (c) 2019, Linaro Limited
|
* Copyright (c) 2019, Linaro Limited
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <rand.h>
|
#include <rand.h>
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
#include <time.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
static int sandbox_rng_read(struct udevice *dev, void *data, size_t len)
|
static int sandbox_rng_read(struct udevice *dev, void *data, size_t len)
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#define LOG_CATEGORY UCLASS_RNG
|
#define LOG_CATEGORY UCLASS_RNG
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <linker_lists.h>
|
#include <linker_lists.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
|
|
|
@ -5,16 +5,14 @@
|
||||||
|
|
||||||
#define LOG_CATEGORY UCLASS_RNG
|
#define LOG_CATEGORY UCLASS_RNG
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <reset.h>
|
#include <reset.h>
|
||||||
#include <rng.h>
|
#include <rng.h>
|
||||||
|
#include <asm/io.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,6 @@ source "fs/cbfs/Kconfig"
|
||||||
|
|
||||||
source "fs/ext4/Kconfig"
|
source "fs/ext4/Kconfig"
|
||||||
|
|
||||||
source "fs/reiserfs/Kconfig"
|
|
||||||
|
|
||||||
source "fs/fat/Kconfig"
|
source "fs/fat/Kconfig"
|
||||||
|
|
||||||
source "fs/jffs2/Kconfig"
|
source "fs/jffs2/Kconfig"
|
||||||
|
|
|
@ -19,7 +19,6 @@ obj-$(CONFIG_CMD_CRAMFS) += cramfs/
|
||||||
obj-$(CONFIG_FS_EXT4) += ext4/
|
obj-$(CONFIG_FS_EXT4) += ext4/
|
||||||
obj-$(CONFIG_FS_FAT) += fat/
|
obj-$(CONFIG_FS_FAT) += fat/
|
||||||
obj-$(CONFIG_FS_JFFS2) += jffs2/
|
obj-$(CONFIG_FS_JFFS2) += jffs2/
|
||||||
obj-$(CONFIG_CMD_REISER) += reiserfs/
|
|
||||||
obj-$(CONFIG_SANDBOX) += sandbox/
|
obj-$(CONFIG_SANDBOX) += sandbox/
|
||||||
obj-$(CONFIG_SEMIHOSTING) += semihostingfs.o
|
obj-$(CONFIG_SEMIHOSTING) += semihostingfs.o
|
||||||
obj-$(CONFIG_CMD_UBIFS) += ubifs/
|
obj-$(CONFIG_CMD_UBIFS) += ubifs/
|
||||||
|
|
|
@ -2214,9 +2214,8 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node)
|
||||||
return symlink;
|
return symlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4fs_find_file1(const char *currpath,
|
int ext4fs_find_file1(const char *currpath, struct ext2fs_node *currroot,
|
||||||
struct ext2fs_node *currroot,
|
struct ext2fs_node **currfound, int *foundtype)
|
||||||
struct ext2fs_node **currfound, int *foundtype)
|
|
||||||
{
|
{
|
||||||
char fpath[strlen(currpath) + 1];
|
char fpath[strlen(currpath) + 1];
|
||||||
char *name = fpath;
|
char *name = fpath;
|
||||||
|
|
|
@ -54,6 +54,8 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, loff_t len,
|
||||||
char *buf, loff_t *actread);
|
char *buf, loff_t *actread);
|
||||||
int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
|
int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
|
||||||
struct ext2fs_node **foundnode, int expecttype);
|
struct ext2fs_node **foundnode, int expecttype);
|
||||||
|
int ext4fs_find_file1(const char *currpath, struct ext2fs_node *currroot,
|
||||||
|
struct ext2fs_node **currfound, int *foundtype);
|
||||||
int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
|
int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
|
||||||
struct ext2fs_node **fnode, int *ftype);
|
struct ext2fs_node **fnode, int *ftype);
|
||||||
|
|
||||||
|
|
|
@ -208,11 +208,14 @@ int ext4fs_ls(const char *dirname)
|
||||||
|
|
||||||
int ext4fs_exists(const char *filename)
|
int ext4fs_exists(const char *filename)
|
||||||
{
|
{
|
||||||
loff_t file_len;
|
struct ext2fs_node *dirnode = NULL;
|
||||||
int ret;
|
int filetype;
|
||||||
|
|
||||||
ret = ext4fs_open(filename, &file_len);
|
if (!filename)
|
||||||
return ret == 0;
|
return 0;
|
||||||
|
|
||||||
|
return ext4fs_find_file1(filename, &ext4fs_root->diropen, &dirnode,
|
||||||
|
&filetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ext4fs_size(const char *filename, loff_t *size)
|
int ext4fs_size(const char *filename, loff_t *size)
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#
|
|
||||||
# (C) Copyright 2006
|
|
||||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
||||||
#
|
|
||||||
# (C) Copyright 2003
|
|
||||||
# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@sysgo.de
|
|
||||||
#
|
|
||||||
|
|
||||||
obj-y := reiserfs.o dev.o mode_string.o
|
|
|
@ -1,28 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* (C) Copyright 2003 - 2004
|
|
||||||
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <config.h>
|
|
||||||
#include <reiserfs.h>
|
|
||||||
#include <fs_internal.h>
|
|
||||||
#include "reiserfs_private.h"
|
|
||||||
|
|
||||||
static struct blk_desc *reiserfs_blk_desc;
|
|
||||||
static struct disk_partition *part_info;
|
|
||||||
|
|
||||||
|
|
||||||
void reiserfs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info)
|
|
||||||
{
|
|
||||||
reiserfs_blk_desc = rbdd;
|
|
||||||
part_info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
int reiserfs_devread(int sector, int byte_offset, int byte_len, char *buf)
|
|
||||||
{
|
|
||||||
return fs_devread(reiserfs_blk_desc, part_info, sector, byte_offset,
|
|
||||||
byte_len, buf);
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* mode_string implementation for busybox
|
|
||||||
*
|
|
||||||
* Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Aug 13, 2003
|
|
||||||
* Fix a bug reported by junkio@cox.net involving the mode_chars index.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <linux/stat.h>
|
|
||||||
|
|
||||||
#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \
|
|
||||||
|| ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \
|
|
||||||
|| ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \
|
|
||||||
|| ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 )
|
|
||||||
#error permission bitflag value assumption(s) violated!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
|
|
||||||
|| ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \
|
|
||||||
|| ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
|
|
||||||
|| ( S_IFIFO != 0010000 )
|
|
||||||
#warning mode type bitflag value assumption(s) violated! falling back to larger version
|
|
||||||
|
|
||||||
#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777
|
|
||||||
#undef mode_t
|
|
||||||
#define mode_t unsigned short
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const mode_t mode_flags[] = {
|
|
||||||
S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
|
|
||||||
S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
|
|
||||||
S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The static const char arrays below are duplicated for the two cases
|
|
||||||
* because moving them ahead of the mode_flags declaration cause a text
|
|
||||||
* size increase with the gcc version I'm using. */
|
|
||||||
|
|
||||||
/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C',
|
|
||||||
* and 'B' types don't appear to be available on linux. So I removed them. */
|
|
||||||
static const char type_chars[16] = "?pc?d?b?-?l?s???";
|
|
||||||
/* 0123456789abcdef */
|
|
||||||
static const char mode_chars[7] = "rwxSTst";
|
|
||||||
|
|
||||||
const char *bb_mode_string(int mode)
|
|
||||||
{
|
|
||||||
static char buf[12];
|
|
||||||
char *p = buf;
|
|
||||||
|
|
||||||
int i, j, k;
|
|
||||||
|
|
||||||
*p = type_chars[ (mode >> 12) & 0xf ];
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
j = k = 0;
|
|
||||||
do {
|
|
||||||
*++p = '-';
|
|
||||||
if (mode & mode_flags[i+j]) {
|
|
||||||
*p = mode_chars[j];
|
|
||||||
k = j;
|
|
||||||
}
|
|
||||||
} while (++j < 3);
|
|
||||||
if (mode & mode_flags[i+j]) {
|
|
||||||
*p = mode_chars[3 + (k & 2) + ((i&8) >> 3)];
|
|
||||||
}
|
|
||||||
i += 4;
|
|
||||||
} while (i < 12);
|
|
||||||
|
|
||||||
/* Note: We don't bother with nul termination because bss initialization
|
|
||||||
* should have taken care of that for us. If the user scribbled in buf
|
|
||||||
* memory, they deserve whatever happens. But we'll at least assert. */
|
|
||||||
if (buf[10] != 0) return NULL;
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C',
|
|
||||||
* and 'B' types don't appear to be available on linux. So I removed them. */
|
|
||||||
static const char type_chars[16] = "?pc?d?b?-?l?s???";
|
|
||||||
/* 0123456789abcdef */
|
|
||||||
static const char mode_chars[7] = "rwxSTst";
|
|
||||||
|
|
||||||
const char *bb_mode_string(int mode)
|
|
||||||
{
|
|
||||||
static char buf[12];
|
|
||||||
char *p = buf;
|
|
||||||
|
|
||||||
int i, j, k, m;
|
|
||||||
|
|
||||||
*p = type_chars[ (mode >> 12) & 0xf ];
|
|
||||||
i = 0;
|
|
||||||
m = 0400;
|
|
||||||
do {
|
|
||||||
j = k = 0;
|
|
||||||
do {
|
|
||||||
*++p = '-';
|
|
||||||
if (mode & m) {
|
|
||||||
*p = mode_chars[j];
|
|
||||||
k = j;
|
|
||||||
}
|
|
||||||
m >>= 1;
|
|
||||||
} while (++j < 3);
|
|
||||||
++i;
|
|
||||||
if (mode & (010000 >> i)) {
|
|
||||||
*p = mode_chars[3 + (k & 2) + (i == 3)];
|
|
||||||
}
|
|
||||||
} while (i < 3);
|
|
||||||
|
|
||||||
/* Note: We don't bother with nul termination because bss initialization
|
|
||||||
* should have taken care of that for us. If the user scribbled in buf
|
|
||||||
* memory, they deserve whatever happens. But we'll at least assert. */
|
|
||||||
if (buf[10] != 0) return NULL;
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,971 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
|
|
||||||
*
|
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* (C) Copyright 2003 - 2004
|
|
||||||
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* An implementation for the ReiserFS filesystem ported from GRUB.
|
|
||||||
* Some parts of this code (mainly the structures and defines) are
|
|
||||||
* from the original reiser fs code, as found in the linux kernel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <asm/byteorder.h>
|
|
||||||
#include <reiserfs.h>
|
|
||||||
|
|
||||||
#include "reiserfs_private.h"
|
|
||||||
|
|
||||||
#undef REISERDEBUG
|
|
||||||
|
|
||||||
/* Some parts of this code (mainly the structures and defines) are
|
|
||||||
* from the original reiser fs code, as found in the linux kernel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static char fsys_buf[FSYS_BUFLEN];
|
|
||||||
static reiserfs_error_t errnum = ERR_NONE;
|
|
||||||
static int print_possibilities;
|
|
||||||
static unsigned int filepos, filemax;
|
|
||||||
|
|
||||||
static int
|
|
||||||
substring (const char *s1, const char *s2)
|
|
||||||
{
|
|
||||||
while (*s1 == *s2)
|
|
||||||
{
|
|
||||||
/* The strings match exactly. */
|
|
||||||
if (! *(s1++))
|
|
||||||
return 0;
|
|
||||||
s2 ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* S1 is a substring of S2. */
|
|
||||||
if (*s1 == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* S1 isn't a substring. */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sd_print_item (struct item_head * ih, char * item)
|
|
||||||
{
|
|
||||||
char filetime[30];
|
|
||||||
time_t ttime;
|
|
||||||
|
|
||||||
if (stat_data_v1 (ih)) {
|
|
||||||
struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
|
|
||||||
ttime = sd_v1_mtime(sd);
|
|
||||||
ctime_r(&ttime, filetime);
|
|
||||||
printf ("%-10s %4hd %6d %6d %9d %24.24s",
|
|
||||||
bb_mode_string(sd_v1_mode(sd)), sd_v1_nlink(sd),sd_v1_uid(sd), sd_v1_gid(sd),
|
|
||||||
sd_v1_size(sd), filetime);
|
|
||||||
} else {
|
|
||||||
struct stat_data * sd = (struct stat_data *)item;
|
|
||||||
ttime = sd_v2_mtime(sd);
|
|
||||||
ctime_r(&ttime, filetime);
|
|
||||||
printf ("%-10s %4d %6d %6d %9d %24.24s",
|
|
||||||
bb_mode_string(sd_v2_mode(sd)), sd_v2_nlink(sd),sd_v2_uid(sd),sd_v2_gid(sd),
|
|
||||||
(__u32) sd_v2_size(sd), filetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
journal_read (int block, int len, char *buffer)
|
|
||||||
{
|
|
||||||
return reiserfs_devread ((INFO->journal_block + block) << INFO->blocksize_shift,
|
|
||||||
0, len, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a block from ReiserFS file system, taking the journal into
|
|
||||||
* account. If the block nr is in the journal, the block from the
|
|
||||||
* journal taken.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
block_read (unsigned int blockNr, int start, int len, char *buffer)
|
|
||||||
{
|
|
||||||
int transactions = INFO->journal_transactions;
|
|
||||||
int desc_block = INFO->journal_first_desc;
|
|
||||||
int journal_mask = INFO->journal_block_count - 1;
|
|
||||||
int translatedNr = blockNr;
|
|
||||||
__u32 *journal_table = JOURNAL_START;
|
|
||||||
while (transactions-- > 0)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int j_len;
|
|
||||||
if (__le32_to_cpu(*journal_table) != 0xffffffff)
|
|
||||||
{
|
|
||||||
/* Search for the blockNr in cached journal */
|
|
||||||
j_len = __le32_to_cpu(*journal_table++);
|
|
||||||
while (i++ < j_len)
|
|
||||||
{
|
|
||||||
if (__le32_to_cpu(*journal_table++) == blockNr)
|
|
||||||
{
|
|
||||||
journal_table += j_len - i;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is the end of cached journal marker. The remaining
|
|
||||||
* transactions are still on disk.
|
|
||||||
*/
|
|
||||||
struct reiserfs_journal_desc desc;
|
|
||||||
struct reiserfs_journal_commit commit;
|
|
||||||
|
|
||||||
if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
j_len = __le32_to_cpu(desc.j_len);
|
|
||||||
while (i < j_len && i < JOURNAL_TRANS_HALF)
|
|
||||||
if (__le32_to_cpu(desc.j_realblock[i++]) == blockNr)
|
|
||||||
goto found;
|
|
||||||
|
|
||||||
if (j_len >= JOURNAL_TRANS_HALF)
|
|
||||||
{
|
|
||||||
int commit_block = (desc_block + 1 + j_len) & journal_mask;
|
|
||||||
if (! journal_read (commit_block,
|
|
||||||
sizeof (commit), (char *) &commit))
|
|
||||||
return 0;
|
|
||||||
while (i < j_len)
|
|
||||||
if (__le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
found:
|
|
||||||
translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("block_read: block %d is mapped to journal block %d.\n",
|
|
||||||
blockNr, translatedNr - INFO->journal_block);
|
|
||||||
#endif
|
|
||||||
/* We must continue the search, as this block may be overwritten
|
|
||||||
* in later transactions.
|
|
||||||
*/
|
|
||||||
not_found:
|
|
||||||
desc_block = (desc_block + 2 + j_len) & journal_mask;
|
|
||||||
}
|
|
||||||
return reiserfs_devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init the journal data structure. We try to cache as much as
|
|
||||||
* possible in the JOURNAL_START-JOURNAL_END space, but if it is full
|
|
||||||
* we can still read the rest from the disk on demand.
|
|
||||||
*
|
|
||||||
* The first number of valid transactions and the descriptor block of the
|
|
||||||
* first valid transaction are held in INFO. The transactions are all
|
|
||||||
* adjacent, but we must take care of the journal wrap around.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
journal_init (void)
|
|
||||||
{
|
|
||||||
unsigned int block_count = INFO->journal_block_count;
|
|
||||||
unsigned int desc_block;
|
|
||||||
unsigned int commit_block;
|
|
||||||
unsigned int next_trans_id;
|
|
||||||
struct reiserfs_journal_header header;
|
|
||||||
struct reiserfs_journal_desc desc;
|
|
||||||
struct reiserfs_journal_commit commit;
|
|
||||||
__u32 *journal_table = JOURNAL_START;
|
|
||||||
|
|
||||||
journal_read (block_count, sizeof (header), (char *) &header);
|
|
||||||
desc_block = __le32_to_cpu(header.j_first_unflushed_offset);
|
|
||||||
if (desc_block >= block_count)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
INFO->journal_first_desc = desc_block;
|
|
||||||
next_trans_id = __le32_to_cpu(header.j_last_flush_trans_id) + 1;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("journal_init: last flushed %d\n",
|
|
||||||
__le32_to_cpu(header.j_last_flush_trans_id));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
journal_read (desc_block, sizeof (desc), (char *) &desc);
|
|
||||||
if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
|
|
||||||
|| __le32_to_cpu(desc.j_trans_id) != next_trans_id
|
|
||||||
|| __le32_to_cpu(desc.j_mount_id) != __le32_to_cpu(header.j_mount_id))
|
|
||||||
/* no more valid transactions */
|
|
||||||
break;
|
|
||||||
|
|
||||||
commit_block = (desc_block + __le32_to_cpu(desc.j_len) + 1) & (block_count - 1);
|
|
||||||
journal_read (commit_block, sizeof (commit), (char *) &commit);
|
|
||||||
if (__le32_to_cpu(desc.j_trans_id) != commit.j_trans_id
|
|
||||||
|| __le32_to_cpu(desc.j_len) != __le32_to_cpu(commit.j_len))
|
|
||||||
/* no more valid transactions */
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("Found valid transaction %d/%d at %d.\n",
|
|
||||||
__le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
next_trans_id++;
|
|
||||||
if (journal_table < JOURNAL_END)
|
|
||||||
{
|
|
||||||
if ((journal_table + 1 + __le32_to_cpu(desc.j_len)) >= JOURNAL_END)
|
|
||||||
{
|
|
||||||
/* The table is almost full; mark the end of the cached
|
|
||||||
* journal.*/
|
|
||||||
*journal_table = __cpu_to_le32(0xffffffff);
|
|
||||||
journal_table = JOURNAL_END;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
/* Cache the length and the realblock numbers in the table.
|
|
||||||
* The block number of descriptor can easily be computed.
|
|
||||||
* and need not to be stored here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* both are in the little endian format */
|
|
||||||
*journal_table++ = desc.j_len;
|
|
||||||
for (i = 0; i < __le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++)
|
|
||||||
{
|
|
||||||
/* both are in the little endian format */
|
|
||||||
*journal_table++ = desc.j_realblock[i];
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("block %d is in journal %d.\n",
|
|
||||||
__le32_to_cpu(desc.j_realblock[i]), desc_block);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
for ( ; i < __le32_to_cpu(desc.j_len); i++)
|
|
||||||
{
|
|
||||||
/* both are in the little endian format */
|
|
||||||
*journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("block %d is in journal %d.\n",
|
|
||||||
__le32_to_cpu(commit.j_realblock[i-JOURNAL_TRANS_HALF]),
|
|
||||||
desc_block);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc_block = (commit_block + 1) & (block_count - 1);
|
|
||||||
}
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("Transaction %d/%d at %d isn't valid.\n",
|
|
||||||
__le32_to_cpu(desc.j_trans_id), __le32_to_cpu(desc.j_mount_id), desc_block);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INFO->journal_transactions
|
|
||||||
= next_trans_id - __le32_to_cpu(header.j_last_flush_trans_id) - 1;
|
|
||||||
return errnum == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check filesystem types and read superblock into memory buffer */
|
|
||||||
int
|
|
||||||
reiserfs_mount (unsigned part_length)
|
|
||||||
{
|
|
||||||
struct reiserfs_super_block super;
|
|
||||||
int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
|
|
||||||
char *cache;
|
|
||||||
|
|
||||||
if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
|
|
||||||
|| ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
|
|
||||||
(char *) &super)
|
|
||||||
|| (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
|
|
||||||
&& substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
|
|
||||||
&& substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
|
|
||||||
|| (/* check that this is not a copy inside the journal log */
|
|
||||||
sb_journal_block(&super) * sb_blocksize(&super)
|
|
||||||
<= REISERFS_DISK_OFFSET_IN_BYTES))
|
|
||||||
{
|
|
||||||
/* Try old super block position */
|
|
||||||
superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
|
|
||||||
if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
|
|
||||||
|| ! reiserfs_devread (superblock, 0, sizeof (struct reiserfs_super_block),
|
|
||||||
(char *) &super))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
|
|
||||||
&& substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
|
|
||||||
{
|
|
||||||
/* pre journaling super block ? */
|
|
||||||
if (substring (REISERFS_SUPER_MAGIC_STRING,
|
|
||||||
(char*) ((int) &super + 20)) > 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
set_sb_blocksize(&super, REISERFS_OLD_BLOCKSIZE);
|
|
||||||
set_sb_journal_block(&super, 0);
|
|
||||||
set_sb_version(&super, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check the version number. */
|
|
||||||
if (sb_version(&super) > REISERFS_MAX_SUPPORTED_VERSION)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
INFO->version = sb_version(&super);
|
|
||||||
INFO->blocksize = sb_blocksize(&super);
|
|
||||||
INFO->fullblocksize_shift = log2 (sb_blocksize(&super));
|
|
||||||
INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
|
|
||||||
INFO->cached_slots =
|
|
||||||
(FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("reiserfs_mount: version=%d, blocksize=%d\n",
|
|
||||||
INFO->version, INFO->blocksize);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
/* Clear node cache. */
|
|
||||||
memset (INFO->blocks, 0, sizeof (INFO->blocks));
|
|
||||||
|
|
||||||
if (sb_blocksize(&super) < FSYSREISER_MIN_BLOCKSIZE
|
|
||||||
|| sb_blocksize(&super) > FSYSREISER_MAX_BLOCKSIZE
|
|
||||||
|| (SECTOR_SIZE << INFO->blocksize_shift) != sb_blocksize(&super))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Initialize journal code. If something fails we end with zero
|
|
||||||
* journal_transactions, so we don't access the journal at all.
|
|
||||||
*/
|
|
||||||
INFO->journal_transactions = 0;
|
|
||||||
if (sb_journal_block(&super) != 0 && super.s_journal_dev == 0)
|
|
||||||
{
|
|
||||||
INFO->journal_block = sb_journal_block(&super);
|
|
||||||
INFO->journal_block_count = sb_journal_size(&super);
|
|
||||||
if (is_power_of_two (INFO->journal_block_count))
|
|
||||||
journal_init ();
|
|
||||||
|
|
||||||
/* Read in super block again, maybe it is in the journal */
|
|
||||||
block_read (superblock >> INFO->blocksize_shift,
|
|
||||||
0, sizeof (struct reiserfs_super_block), (char *) &super);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! block_read (sb_root_block(&super), 0, INFO->blocksize, (char*) ROOT))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cache = ROOT;
|
|
||||||
INFO->tree_depth = __le16_to_cpu(BLOCKHEAD (cache)->blk_level);
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("root read_in: block=%d, depth=%d\n",
|
|
||||||
sb_root_block(&super), INFO->tree_depth);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
if (INFO->tree_depth >= MAX_HEIGHT)
|
|
||||||
return 0;
|
|
||||||
if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
|
|
||||||
{
|
|
||||||
/* There is only one node in the whole filesystem,
|
|
||||||
* which is simultanously leaf and root */
|
|
||||||
memcpy (LEAF, ROOT, INFO->blocksize);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************** TREE ACCESSING METHODS *****************************/
|
|
||||||
|
|
||||||
/* I assume you are familiar with the ReiserFS tree, if not go to
|
|
||||||
* http://www.namesys.com/content_table.html
|
|
||||||
*
|
|
||||||
* My tree node cache is organized as following
|
|
||||||
* 0 ROOT node
|
|
||||||
* 1 LEAF node (if the ROOT is also a LEAF it is copied here
|
|
||||||
* 2-n other nodes on current path from bottom to top.
|
|
||||||
* if there is not enough space in the cache, the top most are
|
|
||||||
* omitted.
|
|
||||||
*
|
|
||||||
* I have only two methods to find a key in the tree:
|
|
||||||
* search_stat(dir_id, objectid) searches for the stat entry (always
|
|
||||||
* the first entry) of an object.
|
|
||||||
* next_key() gets the next key in tree order.
|
|
||||||
*
|
|
||||||
* This means, that I can only sequential reads of files are
|
|
||||||
* efficient, but this really doesn't hurt for grub.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Read in the node at the current path and depth into the node cache.
|
|
||||||
* You must set INFO->blocks[depth] before.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
read_tree_node (unsigned int blockNr, int depth)
|
|
||||||
{
|
|
||||||
char* cache = CACHE(depth);
|
|
||||||
int num_cached = INFO->cached_slots;
|
|
||||||
if (depth < num_cached)
|
|
||||||
{
|
|
||||||
/* This is the cached part of the path. Check if same block is
|
|
||||||
* needed.
|
|
||||||
*/
|
|
||||||
if (blockNr == INFO->blocks[depth])
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cache = CACHE(num_cached);
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" next read_in: block=%d (depth=%d)\n",
|
|
||||||
blockNr, depth);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
if (! block_read (blockNr, 0, INFO->blocksize, cache))
|
|
||||||
return 0;
|
|
||||||
/* Make sure it has the right node level */
|
|
||||||
if (__le16_to_cpu(BLOCKHEAD (cache)->blk_level) != depth)
|
|
||||||
{
|
|
||||||
errnum = ERR_FSYS_CORRUPT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO->blocks[depth] = blockNr;
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the next key, i.e. the key following the last retrieved key in
|
|
||||||
* tree order. INFO->current_ih and
|
|
||||||
* INFO->current_info are adapted accordingly. */
|
|
||||||
static int
|
|
||||||
next_key (void)
|
|
||||||
{
|
|
||||||
int depth;
|
|
||||||
struct item_head *ih = INFO->current_ih + 1;
|
|
||||||
char *cache;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n",
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
|
|
||||||
__le16_to_cpu(INFO->current_ih->ih_version));
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
if (ih == &ITEMHEAD[__le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item)])
|
|
||||||
{
|
|
||||||
depth = DISK_LEAF_NODE_LEVEL;
|
|
||||||
/* The last item, was the last in the leaf node.
|
|
||||||
* Read in the next block
|
|
||||||
*/
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (depth == INFO->tree_depth)
|
|
||||||
{
|
|
||||||
/* There are no more keys at all.
|
|
||||||
* Return a dummy item with MAX_KEY */
|
|
||||||
ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
depth++;
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
}
|
|
||||||
while (INFO->next_key_nr[depth] == 0);
|
|
||||||
|
|
||||||
if (depth == INFO->tree_depth)
|
|
||||||
cache = ROOT;
|
|
||||||
else if (depth <= INFO->cached_slots)
|
|
||||||
cache = CACHE (depth);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cache = read_tree_node (INFO->blocks[depth], depth);
|
|
||||||
if (! cache)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
|
|
||||||
int key_nr = INFO->next_key_nr[depth]++;
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
if (key_nr == nr_item)
|
|
||||||
/* This is the last item in this block, set the next_key_nr to 0 */
|
|
||||||
INFO->next_key_nr[depth] = 0;
|
|
||||||
|
|
||||||
cache = read_tree_node (dc_block_number(&(DC (cache)[key_nr])), --depth);
|
|
||||||
if (! cache)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
while (depth > DISK_LEAF_NODE_LEVEL);
|
|
||||||
|
|
||||||
ih = ITEMHEAD;
|
|
||||||
}
|
|
||||||
found:
|
|
||||||
INFO->current_ih = ih;
|
|
||||||
INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" new ih: key %d:%d:%d:%d version:%d\n",
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
|
|
||||||
__le16_to_cpu(INFO->current_ih->ih_version));
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* preconditions: reiserfs_mount already executed, therefore
|
|
||||||
* INFO block is valid
|
|
||||||
* returns: 0 if error (errnum is set),
|
|
||||||
* nonzero iff we were able to find the key successfully.
|
|
||||||
* postconditions: on a nonzero return, the current_ih and
|
|
||||||
* current_item fields describe the key that equals the
|
|
||||||
* searched key. INFO->next_key contains the next key after
|
|
||||||
* the searched key.
|
|
||||||
* side effects: messes around with the cache.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
search_stat (__u32 dir_id, __u32 objectid)
|
|
||||||
{
|
|
||||||
char *cache;
|
|
||||||
int depth;
|
|
||||||
int nr_item;
|
|
||||||
int i;
|
|
||||||
struct item_head *ih;
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
depth = INFO->tree_depth;
|
|
||||||
cache = ROOT;
|
|
||||||
|
|
||||||
while (depth > DISK_LEAF_NODE_LEVEL)
|
|
||||||
{
|
|
||||||
struct key *key;
|
|
||||||
nr_item = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item);
|
|
||||||
|
|
||||||
key = KEY (cache);
|
|
||||||
|
|
||||||
for (i = 0; i < nr_item; i++)
|
|
||||||
{
|
|
||||||
if (__le32_to_cpu(key->k_dir_id) > dir_id
|
|
||||||
|| (__le32_to_cpu(key->k_dir_id) == dir_id
|
|
||||||
&& (__le32_to_cpu(key->k_objectid) > objectid
|
|
||||||
|| (__le32_to_cpu(key->k_objectid) == objectid
|
|
||||||
&& (__le32_to_cpu(key->u.v1.k_offset)
|
|
||||||
| __le32_to_cpu(key->u.v1.k_uniqueness)) > 0))))
|
|
||||||
break;
|
|
||||||
key++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
|
|
||||||
cache = read_tree_node (dc_block_number(&(DC (cache)[i])), --depth);
|
|
||||||
if (! cache)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cache == LEAF */
|
|
||||||
nr_item = __le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item);
|
|
||||||
ih = ITEMHEAD;
|
|
||||||
for (i = 0; i < nr_item; i++)
|
|
||||||
{
|
|
||||||
if (__le32_to_cpu(ih->ih_key.k_dir_id) == dir_id
|
|
||||||
&& __le32_to_cpu(ih->ih_key.k_objectid) == objectid
|
|
||||||
&& __le32_to_cpu(ih->ih_key.u.v1.k_offset) == 0
|
|
||||||
&& __le32_to_cpu(ih->ih_key.u.v1.k_uniqueness) == 0)
|
|
||||||
{
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
INFO->current_ih = ih;
|
|
||||||
INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ih++;
|
|
||||||
}
|
|
||||||
errnum = ERR_FSYS_CORRUPT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
reiserfs_read (char *buf, unsigned len)
|
|
||||||
{
|
|
||||||
unsigned int blocksize;
|
|
||||||
unsigned int offset;
|
|
||||||
unsigned int to_read;
|
|
||||||
char *prev_buf = buf;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("reiserfs_read: filepos=%d len=%d, offset=%Lx\n",
|
|
||||||
filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid
|
|
||||||
|| IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
|
|
||||||
{
|
|
||||||
search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
|
|
||||||
goto get_next_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (! errnum)
|
|
||||||
{
|
|
||||||
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
|
|
||||||
blocksize = __le16_to_cpu(INFO->current_ih->ih_item_len);
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
|
|
||||||
filepos, len, offset, blocksize);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
|
|
||||||
&& offset < blocksize)
|
|
||||||
{
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("direct_read: offset=%d, blocksize=%d\n",
|
|
||||||
offset, blocksize);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
to_read = blocksize - offset;
|
|
||||||
if (to_read > len)
|
|
||||||
to_read = len;
|
|
||||||
|
|
||||||
memcpy (buf, INFO->current_item + offset, to_read);
|
|
||||||
goto update_buf_len;
|
|
||||||
}
|
|
||||||
else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
|
|
||||||
{
|
|
||||||
blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("indirect_read: offset=%d, blocksize=%d\n",
|
|
||||||
offset, blocksize);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
while (offset < blocksize)
|
|
||||||
{
|
|
||||||
__u32 blocknr = __le32_to_cpu(((__u32 *) INFO->current_item)
|
|
||||||
[offset >> INFO->fullblocksize_shift]);
|
|
||||||
int blk_offset = offset & (INFO->blocksize-1);
|
|
||||||
to_read = INFO->blocksize - blk_offset;
|
|
||||||
if (to_read > len)
|
|
||||||
to_read = len;
|
|
||||||
|
|
||||||
/* Journal is only for meta data. Data blocks can be read
|
|
||||||
* directly without using block_read
|
|
||||||
*/
|
|
||||||
reiserfs_devread (blocknr << INFO->blocksize_shift,
|
|
||||||
blk_offset, to_read, buf);
|
|
||||||
update_buf_len:
|
|
||||||
len -= to_read;
|
|
||||||
buf += to_read;
|
|
||||||
offset += to_read;
|
|
||||||
filepos += to_read;
|
|
||||||
if (len == 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get_next_key:
|
|
||||||
next_key ();
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
return errnum ? 0 : buf - prev_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* preconditions: reiserfs_mount already executed, therefore
|
|
||||||
* INFO block is valid
|
|
||||||
* returns: 0 if error, nonzero iff we were able to find the file successfully
|
|
||||||
* postconditions: on a nonzero return, INFO->fileinfo contains the info
|
|
||||||
* of the file we were trying to look up, filepos is 0 and filemax is
|
|
||||||
* the size of the file.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
reiserfs_dir (char *dirname)
|
|
||||||
{
|
|
||||||
struct reiserfs_de_head *de_head;
|
|
||||||
char *rest, ch;
|
|
||||||
__u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
|
|
||||||
#ifndef STAGE1_5
|
|
||||||
int do_possibilities = 0;
|
|
||||||
#endif /* ! STAGE1_5 */
|
|
||||||
char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
|
|
||||||
int link_count = 0;
|
|
||||||
int mode;
|
|
||||||
|
|
||||||
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
|
|
||||||
objectid = REISERFS_ROOT_OBJECTID;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("dirname=%s\n", dirname);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
/* Search for the stat info first. */
|
|
||||||
if (! search_stat (dir_id, objectid))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("sd_mode=%x sd_size=%d\n",
|
|
||||||
stat_data_v1(INFO->current_ih) ? sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
|
|
||||||
sd_v2_mode((struct stat_data *) (INFO->current_item)),
|
|
||||||
stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
|
|
||||||
sd_v2_size((struct stat_data *) INFO->current_item)
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
mode = stat_data_v1(INFO->current_ih) ?
|
|
||||||
sd_v1_mode((struct stat_data_v1 *) INFO->current_item) :
|
|
||||||
sd_v2_mode((struct stat_data *) INFO->current_item);
|
|
||||||
|
|
||||||
/* If we've got a symbolic link, then chase it. */
|
|
||||||
if (S_ISLNK (mode))
|
|
||||||
{
|
|
||||||
unsigned int len;
|
|
||||||
if (++link_count > MAX_LINK_COUNT)
|
|
||||||
{
|
|
||||||
errnum = ERR_SYMLINK_LOOP;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the symlink size. */
|
|
||||||
filemax = stat_data_v1(INFO->current_ih) ?
|
|
||||||
sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
|
|
||||||
sd_v2_size((struct stat_data *) INFO->current_item);
|
|
||||||
|
|
||||||
/* Find out how long our remaining name is. */
|
|
||||||
len = 0;
|
|
||||||
while (dirname[len] && !isspace (dirname[len]))
|
|
||||||
len++;
|
|
||||||
|
|
||||||
if (filemax + len > sizeof (linkbuf) - 1)
|
|
||||||
{
|
|
||||||
errnum = ERR_FILELENGTH;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the remaining name to the end of the symlink data.
|
|
||||||
Note that DIRNAME and LINKBUF may overlap! */
|
|
||||||
memmove (linkbuf + filemax, dirname, len+1);
|
|
||||||
|
|
||||||
INFO->fileinfo.k_dir_id = dir_id;
|
|
||||||
INFO->fileinfo.k_objectid = objectid;
|
|
||||||
filepos = 0;
|
|
||||||
if (! next_key ()
|
|
||||||
|| reiserfs_read (linkbuf, filemax) != filemax)
|
|
||||||
{
|
|
||||||
if (! errnum)
|
|
||||||
errnum = ERR_FSYS_CORRUPT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("symlink=%s\n", linkbuf);
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
dirname = linkbuf;
|
|
||||||
if (*dirname == '/')
|
|
||||||
{
|
|
||||||
/* It's an absolute link, so look it up in root. */
|
|
||||||
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
|
|
||||||
objectid = REISERFS_ROOT_OBJECTID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Relative, so look it up in our parent directory. */
|
|
||||||
dir_id = parent_dir_id;
|
|
||||||
objectid = parent_objectid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now lookup the new name. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we have a real file (and we're not just printing possibilities),
|
|
||||||
then this is where we want to exit */
|
|
||||||
|
|
||||||
if (! *dirname || isspace (*dirname))
|
|
||||||
{
|
|
||||||
if (! S_ISREG (mode))
|
|
||||||
{
|
|
||||||
errnum = ERR_BAD_FILETYPE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
filepos = 0;
|
|
||||||
filemax = stat_data_v1(INFO->current_ih) ?
|
|
||||||
sd_v1_size((struct stat_data_v1 *) INFO->current_item) :
|
|
||||||
sd_v2_size((struct stat_data *) INFO->current_item);
|
|
||||||
#if 0
|
|
||||||
/* If this is a new stat data and size is > 4GB set filemax to
|
|
||||||
* maximum
|
|
||||||
*/
|
|
||||||
if (__le16_to_cpu(INFO->current_ih->ih_version) == ITEM_VERSION_2
|
|
||||||
&& sd_size_hi((struct stat_data *) INFO->current_item) > 0)
|
|
||||||
filemax = 0xffffffff;
|
|
||||||
#endif
|
|
||||||
INFO->fileinfo.k_dir_id = dir_id;
|
|
||||||
INFO->fileinfo.k_objectid = objectid;
|
|
||||||
return next_key ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* continue with the file/directory name interpretation */
|
|
||||||
while (*dirname == '/')
|
|
||||||
dirname++;
|
|
||||||
if (! S_ISDIR (mode))
|
|
||||||
{
|
|
||||||
errnum = ERR_BAD_FILETYPE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
|
|
||||||
*rest = 0;
|
|
||||||
|
|
||||||
# ifndef STAGE1_5
|
|
||||||
if (print_possibilities && ch != '/')
|
|
||||||
do_possibilities = 1;
|
|
||||||
# endif /* ! STAGE1_5 */
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
char *name_end;
|
|
||||||
int num_entries;
|
|
||||||
|
|
||||||
if (! next_key ())
|
|
||||||
return 0;
|
|
||||||
#ifdef REISERDEBUG
|
|
||||||
printf ("ih: key %d:%d:%d:%d version:%d\n",
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset),
|
|
||||||
__le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness),
|
|
||||||
__le16_to_cpu(INFO->current_ih->ih_version));
|
|
||||||
#endif /* REISERDEBUG */
|
|
||||||
|
|
||||||
if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != objectid)
|
|
||||||
break;
|
|
||||||
|
|
||||||
name_end = INFO->current_item + __le16_to_cpu(INFO->current_ih->ih_item_len);
|
|
||||||
de_head = (struct reiserfs_de_head *) INFO->current_item;
|
|
||||||
num_entries = __le16_to_cpu(INFO->current_ih->u.ih_entry_count);
|
|
||||||
while (num_entries > 0)
|
|
||||||
{
|
|
||||||
char *filename = INFO->current_item + deh_location(de_head);
|
|
||||||
char tmp = *name_end;
|
|
||||||
if ((deh_state(de_head) & DEH_Visible))
|
|
||||||
{
|
|
||||||
int cmp;
|
|
||||||
/* Directory names in ReiserFS are not null
|
|
||||||
* terminated. We write a temporary 0 behind it.
|
|
||||||
* NOTE: that this may overwrite the first block in
|
|
||||||
* the tree cache. That doesn't hurt as long as we
|
|
||||||
* don't call next_key () in between.
|
|
||||||
*/
|
|
||||||
*name_end = 0;
|
|
||||||
cmp = substring (dirname, filename);
|
|
||||||
*name_end = tmp;
|
|
||||||
# ifndef STAGE1_5
|
|
||||||
if (do_possibilities)
|
|
||||||
{
|
|
||||||
if (cmp <= 0)
|
|
||||||
{
|
|
||||||
char fn[PATH_MAX];
|
|
||||||
struct fsys_reiser_info info_save;
|
|
||||||
|
|
||||||
if (print_possibilities > 0)
|
|
||||||
print_possibilities = -print_possibilities;
|
|
||||||
*name_end = 0;
|
|
||||||
strcpy(fn, filename);
|
|
||||||
*name_end = tmp;
|
|
||||||
|
|
||||||
/* If NAME is "." or "..", do not count it. */
|
|
||||||
if (strcmp (fn, ".") != 0 && strcmp (fn, "..") != 0) {
|
|
||||||
memcpy(&info_save, INFO, sizeof(struct fsys_reiser_info));
|
|
||||||
search_stat (deh_dir_id(de_head), deh_objectid(de_head));
|
|
||||||
sd_print_item(INFO->current_ih, INFO->current_item);
|
|
||||||
printf(" %s\n", fn);
|
|
||||||
search_stat (dir_id, objectid);
|
|
||||||
memcpy(INFO, &info_save, sizeof(struct fsys_reiser_info));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
# endif /* ! STAGE1_5 */
|
|
||||||
if (cmp == 0)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
/* The beginning of this name marks the end of the next name.
|
|
||||||
*/
|
|
||||||
name_end = filename;
|
|
||||||
de_head++;
|
|
||||||
num_entries--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifndef STAGE1_5
|
|
||||||
if (print_possibilities < 0)
|
|
||||||
return 1;
|
|
||||||
# endif /* ! STAGE1_5 */
|
|
||||||
|
|
||||||
errnum = ERR_FILE_NOT_FOUND;
|
|
||||||
*rest = ch;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
found:
|
|
||||||
*rest = ch;
|
|
||||||
dirname = rest;
|
|
||||||
|
|
||||||
parent_dir_id = dir_id;
|
|
||||||
parent_objectid = objectid;
|
|
||||||
dir_id = deh_dir_id(de_head);
|
|
||||||
objectid = deh_objectid(de_head);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* U-Boot interface functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List given directory
|
|
||||||
*
|
|
||||||
* RETURN: 0 - OK, else grub_error_t errnum
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
reiserfs_ls (char *dirname)
|
|
||||||
{
|
|
||||||
char *dir_slash;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
errnum = 0;
|
|
||||||
dir_slash = malloc(strlen(dirname) + 1);
|
|
||||||
if (dir_slash == NULL) {
|
|
||||||
return ERR_NUMBER_OVERFLOW;
|
|
||||||
}
|
|
||||||
strcpy(dir_slash, dirname);
|
|
||||||
/* add "/" to the directory name */
|
|
||||||
strcat(dir_slash, "/");
|
|
||||||
|
|
||||||
print_possibilities = 1;
|
|
||||||
res = reiserfs_dir (dir_slash);
|
|
||||||
free(dir_slash);
|
|
||||||
if (!res || errnum) {
|
|
||||||
return errnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open file for reading
|
|
||||||
*
|
|
||||||
* RETURN: >0 - OK, size of opened file
|
|
||||||
* <0 - ERROR -grub_error_t errnum
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
reiserfs_open (char *filename)
|
|
||||||
{
|
|
||||||
/* open the file */
|
|
||||||
errnum = 0;
|
|
||||||
print_possibilities = 0;
|
|
||||||
if (!reiserfs_dir (filename) || errnum) {
|
|
||||||
return -errnum;
|
|
||||||
}
|
|
||||||
return filemax;
|
|
||||||
}
|
|
|
@ -1,509 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
||||||
/*
|
|
||||||
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
|
|
||||||
*
|
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* (C) Copyright 2003 - 2004
|
|
||||||
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* An implementation for the ReiserFS filesystem ported from GRUB.
|
|
||||||
* Some parts of this code (mainly the structures and defines) are
|
|
||||||
* from the original reiser fs code, as found in the linux kernel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <compiler.h>
|
|
||||||
|
|
||||||
#ifndef __BYTE_ORDER
|
|
||||||
#if defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
|
|
||||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
|
||||||
#elif defined(__BIG_ENDIAN) && !defined(__LITTLE_ENDIAN)
|
|
||||||
#define __BYTE_ORDER __BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#error "unable to define __BYTE_ORDER"
|
|
||||||
#endif
|
|
||||||
#endif /* not __BYTE_ORDER */
|
|
||||||
|
|
||||||
#define FSYS_BUFLEN 0x8000
|
|
||||||
#define FSYS_BUF fsys_buf
|
|
||||||
|
|
||||||
/* This is the new super block of a journaling reiserfs system */
|
|
||||||
struct reiserfs_super_block
|
|
||||||
{
|
|
||||||
__u32 s_block_count; /* blocks count */
|
|
||||||
__u32 s_free_blocks; /* free blocks count */
|
|
||||||
__u32 s_root_block; /* root block number */
|
|
||||||
__u32 s_journal_block; /* journal block number */
|
|
||||||
__u32 s_journal_dev; /* journal device number */
|
|
||||||
__u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
|
|
||||||
__u32 s_journal_trans_max; /* max number of blocks in a transaction. */
|
|
||||||
__u32 s_journal_magic; /* random value made on fs creation */
|
|
||||||
__u32 s_journal_max_batch; /* max number of blocks to batch into a trans */
|
|
||||||
__u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */
|
|
||||||
__u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */
|
|
||||||
__u16 s_blocksize; /* block size */
|
|
||||||
__u16 s_oid_maxsize; /* max size of object id array */
|
|
||||||
__u16 s_oid_cursize; /* current size of object id array */
|
|
||||||
__u16 s_state; /* valid or error */
|
|
||||||
char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */
|
|
||||||
__u16 s_tree_height; /* height of disk tree */
|
|
||||||
__u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
|
|
||||||
__u16 s_version;
|
|
||||||
char s_unused[128]; /* zero filled by mkreiserfs */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define sb_root_block(sbp) (__le32_to_cpu((sbp)->s_root_block))
|
|
||||||
#define sb_journal_block(sbp) (__le32_to_cpu((sbp)->s_journal_block))
|
|
||||||
#define set_sb_journal_block(sbp,v) ((sbp)->s_journal_block = __cpu_to_le32(v))
|
|
||||||
#define sb_journal_size(sbp) (__le32_to_cpu((sbp)->s_journal_size))
|
|
||||||
#define sb_blocksize(sbp) (__le16_to_cpu((sbp)->s_blocksize))
|
|
||||||
#define set_sb_blocksize(sbp,v) ((sbp)->s_blocksize = __cpu_to_le16(v))
|
|
||||||
#define sb_version(sbp) (__le16_to_cpu((sbp)->s_version))
|
|
||||||
#define set_sb_version(sbp,v) ((sbp)->s_version = __cpu_to_le16(v))
|
|
||||||
|
|
||||||
|
|
||||||
#define REISERFS_MAX_SUPPORTED_VERSION 2
|
|
||||||
#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
|
|
||||||
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
|
|
||||||
#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs"
|
|
||||||
|
|
||||||
#define MAX_HEIGHT 7
|
|
||||||
|
|
||||||
/* must be correct to keep the desc and commit structs at 4k */
|
|
||||||
#define JOURNAL_TRANS_HALF 1018
|
|
||||||
|
|
||||||
/* first block written in a commit. */
|
|
||||||
struct reiserfs_journal_desc {
|
|
||||||
__u32 j_trans_id; /* id of commit */
|
|
||||||
__u32 j_len; /* length of commit. len +1 is the commit block */
|
|
||||||
__u32 j_mount_id; /* mount id of this trans*/
|
|
||||||
__u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
|
|
||||||
char j_magic[12];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* last block written in a commit */
|
|
||||||
struct reiserfs_journal_commit {
|
|
||||||
__u32 j_trans_id; /* must match j_trans_id from the desc block */
|
|
||||||
__u32 j_len; /* ditto */
|
|
||||||
__u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
|
|
||||||
char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this header block gets written whenever a transaction is considered
|
|
||||||
fully flushed, and is more recent than the last fully flushed
|
|
||||||
transaction.
|
|
||||||
fully flushed means all the log blocks and all the real blocks are
|
|
||||||
on disk, and this transaction does not need to be replayed.
|
|
||||||
*/
|
|
||||||
struct reiserfs_journal_header {
|
|
||||||
/* id of last fully flushed transaction */
|
|
||||||
__u32 j_last_flush_trans_id;
|
|
||||||
/* offset in the log of where to start replay after a crash */
|
|
||||||
__u32 j_first_unflushed_offset;
|
|
||||||
/* mount id to detect very old transactions */
|
|
||||||
__u32 j_mount_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* magic string to find desc blocks in the journal */
|
|
||||||
#define JOURNAL_DESC_MAGIC "ReIsErLB"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* directories use this key as well as old files
|
|
||||||
*/
|
|
||||||
struct offset_v1
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* for regular files this is the offset to the first byte of the
|
|
||||||
* body, contained in the object-item, as measured from the start of
|
|
||||||
* the entire body of the object.
|
|
||||||
*
|
|
||||||
* for directory entries, k_offset consists of hash derived from
|
|
||||||
* hashing the name and using few bits (23 or more) of the resulting
|
|
||||||
* hash, and generation number that allows distinguishing names with
|
|
||||||
* hash collisions. If number of collisions overflows generation
|
|
||||||
* number, we return EEXIST. High order bit is 0 always
|
|
||||||
*/
|
|
||||||
__u32 k_offset;
|
|
||||||
__u32 k_uniqueness;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct offset_v2 {
|
|
||||||
/*
|
|
||||||
* for regular files this is the offset to the first byte of the
|
|
||||||
* body, contained in the object-item, as measured from the start of
|
|
||||||
* the entire body of the object.
|
|
||||||
*
|
|
||||||
* for directory entries, k_offset consists of hash derived from
|
|
||||||
* hashing the name and using few bits (23 or more) of the resulting
|
|
||||||
* hash, and generation number that allows distinguishing names with
|
|
||||||
* hash collisions. If number of collisions overflows generation
|
|
||||||
* number, we return EEXIST. High order bit is 0 always
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
|
||||||
/* little endian version */
|
|
||||||
__u64 k_offset:60;
|
|
||||||
__u64 k_type: 4;
|
|
||||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
|
||||||
/* big endian version */
|
|
||||||
__u64 k_type: 4;
|
|
||||||
__u64 k_offset:60;
|
|
||||||
#else
|
|
||||||
#error "__LITTLE_ENDIAN_BITFIELD or __BIG_ENDIAN_BITFIELD must be defined"
|
|
||||||
#endif
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define TYPE_MAXTYPE 3
|
|
||||||
#define TYPE_ANY 15
|
|
||||||
|
|
||||||
#if (__BYTE_ORDER == __BIG_ENDIAN)
|
|
||||||
typedef union {
|
|
||||||
struct offset_v2 offset_v2;
|
|
||||||
__u64 linear;
|
|
||||||
} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
|
|
||||||
|
|
||||||
static inline __u16 offset_v2_k_type( const struct offset_v2 *v2 )
|
|
||||||
{
|
|
||||||
offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
|
|
||||||
tmp.linear = __le64_to_cpu( tmp.linear );
|
|
||||||
return (tmp.offset_v2.k_type <= TYPE_MAXTYPE)?tmp.offset_v2.k_type:TYPE_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 )
|
|
||||||
{
|
|
||||||
offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
|
|
||||||
tmp.linear = __le64_to_cpu( tmp.linear );
|
|
||||||
return tmp.offset_v2.k_offset;
|
|
||||||
}
|
|
||||||
#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
|
|
||||||
# define offset_v2_k_type(v2) ((v2)->k_type)
|
|
||||||
# define offset_v2_k_offset(v2) ((v2)->k_offset)
|
|
||||||
#else
|
|
||||||
#error "__BYTE_ORDER must be __LITTLE_ENDIAN or __BIG_ENDIAN"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct key
|
|
||||||
{
|
|
||||||
/* packing locality: by default parent directory object id */
|
|
||||||
__u32 k_dir_id;
|
|
||||||
/* object identifier */
|
|
||||||
__u32 k_objectid;
|
|
||||||
/* the offset and node type (old and new form) */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct offset_v1 v1;
|
|
||||||
struct offset_v2 v2;
|
|
||||||
}
|
|
||||||
u;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define KEY_SIZE (sizeof (struct key))
|
|
||||||
|
|
||||||
/* Header of a disk block. More precisely, header of a formatted leaf
|
|
||||||
or internal node, and not the header of an unformatted node. */
|
|
||||||
struct block_head
|
|
||||||
{
|
|
||||||
__u16 blk_level; /* Level of a block in the tree. */
|
|
||||||
__u16 blk_nr_item; /* Number of keys/items in a block. */
|
|
||||||
__u16 blk_free_space; /* Block free space in bytes. */
|
|
||||||
struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
|
|
||||||
only) */
|
|
||||||
};
|
|
||||||
#define BLKH_SIZE (sizeof (struct block_head))
|
|
||||||
#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */
|
|
||||||
|
|
||||||
struct item_head
|
|
||||||
{
|
|
||||||
/* Everything in the tree is found by searching for it based on
|
|
||||||
* its key.*/
|
|
||||||
struct key ih_key;
|
|
||||||
union {
|
|
||||||
/* The free space in the last unformatted node of an
|
|
||||||
indirect item if this is an indirect item. This
|
|
||||||
equals 0xFFFF iff this is a direct item or stat data
|
|
||||||
item. Note that the key, not this field, is used to
|
|
||||||
determine the item type, and thus which field this
|
|
||||||
union contains. */
|
|
||||||
__u16 ih_free_space;
|
|
||||||
/* Iff this is a directory item, this field equals the
|
|
||||||
number of directory entries in the directory item. */
|
|
||||||
__u16 ih_entry_count;
|
|
||||||
} __attribute__ ((__packed__)) u;
|
|
||||||
__u16 ih_item_len; /* total size of the item body */
|
|
||||||
__u16 ih_item_location; /* an offset to the item body
|
|
||||||
* within the block */
|
|
||||||
__u16 ih_version; /* 0 for all old items, 2 for new
|
|
||||||
ones. Highest bit is set by fsck
|
|
||||||
temporary, cleaned after all
|
|
||||||
done */
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
/* size of item header */
|
|
||||||
#define IH_SIZE (sizeof (struct item_head))
|
|
||||||
|
|
||||||
#define ITEM_VERSION_1 0
|
|
||||||
#define ITEM_VERSION_2 1
|
|
||||||
|
|
||||||
#define ih_version(ih) (__le16_to_cpu((ih)->ih_version))
|
|
||||||
|
|
||||||
#define IH_KEY_OFFSET(ih) (ih_version(ih) == ITEM_VERSION_1 \
|
|
||||||
? __le32_to_cpu((ih)->ih_key.u.v1.k_offset) \
|
|
||||||
: offset_v2_k_offset(&((ih)->ih_key.u.v2)))
|
|
||||||
|
|
||||||
#define IH_KEY_ISTYPE(ih, type) (ih_version(ih) == ITEM_VERSION_1 \
|
|
||||||
? __le32_to_cpu((ih)->ih_key.u.v1.k_uniqueness) == V1_##type \
|
|
||||||
: offset_v2_k_type(&((ih)->ih_key.u.v2)) == V2_##type)
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/* DISK CHILD */
|
|
||||||
/***************************************************************************/
|
|
||||||
/* Disk child pointer: The pointer from an internal node of the tree
|
|
||||||
to a node that is on disk. */
|
|
||||||
struct disk_child {
|
|
||||||
__u32 dc_block_number; /* Disk child's block number. */
|
|
||||||
__u16 dc_size; /* Disk child's used space. */
|
|
||||||
__u16 dc_reserved;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DC_SIZE (sizeof(struct disk_child))
|
|
||||||
#define dc_block_number(dc_p) (__le32_to_cpu((dc_p)->dc_block_number))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* old stat data is 32 bytes long. We are going to distinguish new one by
|
|
||||||
* different size
|
|
||||||
*/
|
|
||||||
struct stat_data_v1
|
|
||||||
{
|
|
||||||
__u16 sd_mode; /* file type, permissions */
|
|
||||||
__u16 sd_nlink; /* number of hard links */
|
|
||||||
__u16 sd_uid; /* owner */
|
|
||||||
__u16 sd_gid; /* group */
|
|
||||||
__u32 sd_size; /* file size */
|
|
||||||
__u32 sd_atime; /* time of last access */
|
|
||||||
__u32 sd_mtime; /* time file was last modified */
|
|
||||||
__u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
|
|
||||||
union {
|
|
||||||
__u32 sd_rdev;
|
|
||||||
__u32 sd_blocks; /* number of blocks file uses */
|
|
||||||
} __attribute__ ((__packed__)) u;
|
|
||||||
__u32 sd_first_direct_byte; /* first byte of file which is stored
|
|
||||||
in a direct item: except that if it
|
|
||||||
equals 1 it is a symlink and if it
|
|
||||||
equals ~(__u32)0 there is no
|
|
||||||
direct item. The existence of this
|
|
||||||
field really grates on me. Let's
|
|
||||||
replace it with a macro based on
|
|
||||||
sd_size and our tail suppression
|
|
||||||
policy. Someday. -Hans */
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define stat_data_v1(ih) (ih_version(ih) == ITEM_VERSION_1)
|
|
||||||
#define sd_v1_mode(sdp) ((sdp)->sd_mode)
|
|
||||||
#define sd_v1_nlink(sdp) (__le16_to_cpu((sdp)->sd_nlink))
|
|
||||||
#define sd_v1_uid(sdp) (__le16_to_cpu((sdp)->sd_uid))
|
|
||||||
#define sd_v1_gid(sdp) (__le16_to_cpu((sdp)->sd_gid))
|
|
||||||
#define sd_v1_size(sdp) (__le32_to_cpu((sdp)->sd_size))
|
|
||||||
#define sd_v1_mtime(sdp) (__le32_to_cpu((sdp)->sd_mtime))
|
|
||||||
|
|
||||||
/* Stat Data on disk (reiserfs version of UFS disk inode minus the
|
|
||||||
address blocks) */
|
|
||||||
struct stat_data {
|
|
||||||
__u16 sd_mode; /* file type, permissions */
|
|
||||||
__u16 sd_attrs; /* persistent inode flags */
|
|
||||||
__u32 sd_nlink; /* number of hard links */
|
|
||||||
__u64 sd_size; /* file size */
|
|
||||||
__u32 sd_uid; /* owner */
|
|
||||||
__u32 sd_gid; /* group */
|
|
||||||
__u32 sd_atime; /* time of last access */
|
|
||||||
__u32 sd_mtime; /* time file was last modified */
|
|
||||||
__u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
|
|
||||||
__u32 sd_blocks;
|
|
||||||
union {
|
|
||||||
__u32 sd_rdev;
|
|
||||||
__u32 sd_generation;
|
|
||||||
/*__u32 sd_first_direct_byte; */
|
|
||||||
/* first byte of file which is stored in a
|
|
||||||
direct item: except that if it equals 1
|
|
||||||
it is a symlink and if it equals
|
|
||||||
~(__u32)0 there is no direct item. The
|
|
||||||
existence of this field really grates
|
|
||||||
on me. Let's replace it with a macro
|
|
||||||
based on sd_size and our tail
|
|
||||||
suppression policy? */
|
|
||||||
} __attribute__ ((__packed__)) u;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define stat_data_v2(ih) (ih_version(ih) == ITEM_VERSION_2)
|
|
||||||
#define sd_v2_mode(sdp) (__le16_to_cpu((sdp)->sd_mode))
|
|
||||||
#define sd_v2_nlink(sdp) (__le32_to_cpu((sdp)->sd_nlink))
|
|
||||||
#define sd_v2_size(sdp) (__le64_to_cpu((sdp)->sd_size))
|
|
||||||
#define sd_v2_uid(sdp) (__le32_to_cpu((sdp)->sd_uid))
|
|
||||||
#define sd_v2_gid(sdp) (__le32_to_cpu((sdp)->sd_gid))
|
|
||||||
#define sd_v2_mtime(sdp) (__le32_to_cpu((sdp)->sd_mtime))
|
|
||||||
|
|
||||||
#define sd_mode(sdp) (__le16_to_cpu((sdp)->sd_mode))
|
|
||||||
#define sd_size(sdp) (__le32_to_cpu((sdp)->sd_size))
|
|
||||||
#define sd_size_hi(sdp) (__le32_to_cpu((sdp)->sd_size_hi))
|
|
||||||
|
|
||||||
struct reiserfs_de_head
|
|
||||||
{
|
|
||||||
__u32 deh_offset; /* third component of the directory entry key */
|
|
||||||
__u32 deh_dir_id; /* objectid of the parent directory of the
|
|
||||||
object, that is referenced by directory entry */
|
|
||||||
__u32 deh_objectid;/* objectid of the object, that is referenced by
|
|
||||||
directory entry */
|
|
||||||
__u16 deh_location;/* offset of name in the whole item */
|
|
||||||
__u16 deh_state; /* whether 1) entry contains stat data (for
|
|
||||||
future), and 2) whether entry is hidden
|
|
||||||
(unlinked) */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEH_SIZE (sizeof (struct reiserfs_de_head))
|
|
||||||
#define deh_offset(p_deh) (__le32_to_cpu((p_deh)->deh_offset))
|
|
||||||
#define deh_dir_id(p_deh) (__le32_to_cpu((p_deh)->deh_dir_id))
|
|
||||||
#define deh_objectid(p_deh) (__le32_to_cpu((p_deh)->deh_objectid))
|
|
||||||
#define deh_location(p_deh) (__le16_to_cpu((p_deh)->deh_location))
|
|
||||||
#define deh_state(p_deh) (__le16_to_cpu((p_deh)->deh_state))
|
|
||||||
|
|
||||||
|
|
||||||
#define DEH_Statdata (1 << 0) /* not used now */
|
|
||||||
#define DEH_Visible (1 << 2)
|
|
||||||
|
|
||||||
#define SD_OFFSET 0
|
|
||||||
#define SD_UNIQUENESS 0
|
|
||||||
#define DOT_OFFSET 1
|
|
||||||
#define DOT_DOT_OFFSET 2
|
|
||||||
#define DIRENTRY_UNIQUENESS 500
|
|
||||||
|
|
||||||
#define V1_TYPE_STAT_DATA 0x0
|
|
||||||
#define V1_TYPE_DIRECT 0xffffffff
|
|
||||||
#define V1_TYPE_INDIRECT 0xfffffffe
|
|
||||||
#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
|
|
||||||
#define V2_TYPE_STAT_DATA 0
|
|
||||||
#define V2_TYPE_INDIRECT 1
|
|
||||||
#define V2_TYPE_DIRECT 2
|
|
||||||
#define V2_TYPE_DIRENTRY 3
|
|
||||||
|
|
||||||
#define REISERFS_ROOT_OBJECTID 2
|
|
||||||
#define REISERFS_ROOT_PARENT_OBJECTID 1
|
|
||||||
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
|
|
||||||
/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
|
|
||||||
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
|
|
||||||
#define REISERFS_OLD_BLOCKSIZE 4096
|
|
||||||
|
|
||||||
#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
|
|
||||||
#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
|
|
||||||
#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
|
|
||||||
|
|
||||||
#define PATH_MAX 1024 /* include/linux/limits.h */
|
|
||||||
#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
|
|
||||||
|
|
||||||
/* The size of the node cache */
|
|
||||||
#define FSYSREISER_CACHE_SIZE 24*1024
|
|
||||||
#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
|
|
||||||
#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
|
|
||||||
|
|
||||||
/* Info about currently opened file */
|
|
||||||
struct fsys_reiser_fileinfo
|
|
||||||
{
|
|
||||||
__u32 k_dir_id;
|
|
||||||
__u32 k_objectid;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* In memory info about the currently mounted filesystem */
|
|
||||||
struct fsys_reiser_info
|
|
||||||
{
|
|
||||||
/* The last read item head */
|
|
||||||
struct item_head *current_ih;
|
|
||||||
/* The last read item */
|
|
||||||
char *current_item;
|
|
||||||
/* The information for the currently opened file */
|
|
||||||
struct fsys_reiser_fileinfo fileinfo;
|
|
||||||
/* The start of the journal */
|
|
||||||
__u32 journal_block;
|
|
||||||
/* The size of the journal */
|
|
||||||
__u32 journal_block_count;
|
|
||||||
/* The first valid descriptor block in journal
|
|
||||||
(relative to journal_block) */
|
|
||||||
__u32 journal_first_desc;
|
|
||||||
|
|
||||||
/* The ReiserFS version. */
|
|
||||||
__u16 version;
|
|
||||||
/* The current depth of the reiser tree. */
|
|
||||||
__u16 tree_depth;
|
|
||||||
/* SECTOR_SIZE << blocksize_shift == blocksize. */
|
|
||||||
__u8 blocksize_shift;
|
|
||||||
/* 1 << full_blocksize_shift == blocksize. */
|
|
||||||
__u8 fullblocksize_shift;
|
|
||||||
/* The reiserfs block size (must be a power of 2) */
|
|
||||||
__u16 blocksize;
|
|
||||||
/* The number of cached tree nodes */
|
|
||||||
__u16 cached_slots;
|
|
||||||
/* The number of valid transactions in journal */
|
|
||||||
__u16 journal_transactions;
|
|
||||||
|
|
||||||
unsigned int blocks[MAX_HEIGHT];
|
|
||||||
unsigned int next_key_nr[MAX_HEIGHT];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The cached s+tree blocks in FSYS_BUF, see below
|
|
||||||
* for a more detailed description.
|
|
||||||
*/
|
|
||||||
#define ROOT ((char *) ((int) FSYS_BUF))
|
|
||||||
#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
|
|
||||||
#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
|
|
||||||
|
|
||||||
#define BLOCKHEAD(cache) ((struct block_head *) cache)
|
|
||||||
#define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE))
|
|
||||||
#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE))
|
|
||||||
#define DC(cache) ((struct disk_child *) \
|
|
||||||
((int) cache + BLKH_SIZE + KEY_SIZE * nr_item))
|
|
||||||
/* The fsys_reiser_info block.
|
|
||||||
*/
|
|
||||||
#define INFO \
|
|
||||||
((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
|
|
||||||
/*
|
|
||||||
* The journal cache. For each transaction it contains the number of
|
|
||||||
* blocks followed by the real block numbers of this transaction.
|
|
||||||
*
|
|
||||||
* If the block numbers of some transaction won't fit in this space,
|
|
||||||
* this list is stopped with a 0xffffffff marker and the remaining
|
|
||||||
* uncommitted transactions aren't cached.
|
|
||||||
*/
|
|
||||||
#define JOURNAL_START ((__u32 *) (INFO + 1))
|
|
||||||
#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
|
|
||||||
|
|
||||||
|
|
||||||
static __inline__ unsigned long
|
|
||||||
log2 (unsigned long word)
|
|
||||||
{
|
|
||||||
#ifdef __I386__
|
|
||||||
__asm__ ("bsfl %1,%0"
|
|
||||||
: "=r" (word)
|
|
||||||
: "r" (word));
|
|
||||||
return word;
|
|
||||||
#else
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i=0; i<(8*sizeof(word)); i++)
|
|
||||||
if ((1<<i) & word)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ int
|
|
||||||
is_power_of_two (unsigned long word)
|
|
||||||
{
|
|
||||||
return (word & -word) == word;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const char *bb_mode_string(int mode);
|
|
||||||
extern int reiserfs_devread (int sector, int byte_offset, int byte_len, char *buf);
|
|
|
@ -133,6 +133,8 @@ struct bootflow {
|
||||||
* this uclass (used with things like "mmc")
|
* this uclass (used with things like "mmc")
|
||||||
* @BOOTFLOWIF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used
|
* @BOOTFLOWIF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used
|
||||||
* with things like "mmc1")
|
* with things like "mmc1")
|
||||||
|
* @BOOTFLOWIF_SINGLE_PARTITION: (internal) Scan one partition in media device
|
||||||
|
* (used with things like "mmc1:3")
|
||||||
*/
|
*/
|
||||||
enum bootflow_iter_flags_t {
|
enum bootflow_iter_flags_t {
|
||||||
BOOTFLOWIF_FIXED = 1 << 0,
|
BOOTFLOWIF_FIXED = 1 << 0,
|
||||||
|
@ -148,6 +150,7 @@ enum bootflow_iter_flags_t {
|
||||||
BOOTFLOWIF_SKIP_GLOBAL = 1 << 17,
|
BOOTFLOWIF_SKIP_GLOBAL = 1 << 17,
|
||||||
BOOTFLOWIF_SINGLE_UCLASS = 1 << 18,
|
BOOTFLOWIF_SINGLE_UCLASS = 1 << 18,
|
||||||
BOOTFLOWIF_SINGLE_MEDIA = 1 << 19,
|
BOOTFLOWIF_SINGLE_MEDIA = 1 << 19,
|
||||||
|
BOOTFLOWIF_SINGLE_PARTITION = 1 << 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
/*
|
/*
|
||||||
* Boot info
|
* Boot info
|
||||||
*/
|
*/
|
||||||
|
#define SCB_PLAT_METADATA_OFFSET (0x510000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hardware drivers support
|
* Hardware drivers support
|
||||||
|
|
|
@ -688,4 +688,16 @@ static inline int log_get_default_format(void)
|
||||||
(IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
|
(IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct global_data;
|
||||||
|
/**
|
||||||
|
* log_fixup_for_gd_move() - Handle global_data moving to a new place
|
||||||
|
*
|
||||||
|
* @new_gd: Pointer to the new global data
|
||||||
|
*
|
||||||
|
* The log_head list is part of global_data. Due to the way lists work, moving
|
||||||
|
* the list will cause it to become invalid. This function fixes that up so
|
||||||
|
* that the log_head list will work correctly.
|
||||||
|
*/
|
||||||
|
void log_fixup_for_gd_move(struct global_data *new_gd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
||||||
/*
|
|
||||||
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
|
|
||||||
*
|
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* (C) Copyright 2003 Sysgo Real-Time Solutions, AG <www.elinos.com>
|
|
||||||
* Pavel Bartusek <pba@sysgo.de>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* An implementation for the ReiserFS filesystem ported from GRUB.
|
|
||||||
* Some parts of this code (mainly the structures and defines) are
|
|
||||||
* from the original reiser fs code, as found in the linux kernel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define SECTOR_SIZE 0x200
|
|
||||||
#define SECTOR_BITS 9
|
|
||||||
|
|
||||||
struct blk_desc;
|
|
||||||
struct disk_partition;
|
|
||||||
|
|
||||||
/* Error codes */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ERR_NONE = 0,
|
|
||||||
ERR_BAD_FILENAME,
|
|
||||||
ERR_BAD_FILETYPE,
|
|
||||||
ERR_BAD_GZIP_DATA,
|
|
||||||
ERR_BAD_GZIP_HEADER,
|
|
||||||
ERR_BAD_PART_TABLE,
|
|
||||||
ERR_BAD_VERSION,
|
|
||||||
ERR_BELOW_1MB,
|
|
||||||
ERR_BOOT_COMMAND,
|
|
||||||
ERR_BOOT_FAILURE,
|
|
||||||
ERR_BOOT_FEATURES,
|
|
||||||
ERR_DEV_FORMAT,
|
|
||||||
ERR_DEV_VALUES,
|
|
||||||
ERR_EXEC_FORMAT,
|
|
||||||
ERR_FILELENGTH,
|
|
||||||
ERR_FILE_NOT_FOUND,
|
|
||||||
ERR_FSYS_CORRUPT,
|
|
||||||
ERR_FSYS_MOUNT,
|
|
||||||
ERR_GEOM,
|
|
||||||
ERR_NEED_LX_KERNEL,
|
|
||||||
ERR_NEED_MB_KERNEL,
|
|
||||||
ERR_NO_DISK,
|
|
||||||
ERR_NO_PART,
|
|
||||||
ERR_NUMBER_PARSING,
|
|
||||||
ERR_OUTSIDE_PART,
|
|
||||||
ERR_READ,
|
|
||||||
ERR_SYMLINK_LOOP,
|
|
||||||
ERR_UNRECOGNIZED,
|
|
||||||
ERR_WONT_FIT,
|
|
||||||
ERR_WRITE,
|
|
||||||
ERR_BAD_ARGUMENT,
|
|
||||||
ERR_UNALIGNED,
|
|
||||||
ERR_PRIVILEGED,
|
|
||||||
ERR_DEV_NEED_INIT,
|
|
||||||
ERR_NO_DISK_SPACE,
|
|
||||||
ERR_NUMBER_OVERFLOW,
|
|
||||||
|
|
||||||
MAX_ERR_NUM
|
|
||||||
} reiserfs_error_t;
|
|
||||||
|
|
||||||
|
|
||||||
void reiserfs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
|
|
||||||
extern int reiserfs_ls (char *dirname);
|
|
||||||
extern int reiserfs_open (char *filename);
|
|
||||||
extern int reiserfs_read (char *buf, unsigned len);
|
|
||||||
extern int reiserfs_mount (unsigned part_length);
|
|
|
@ -6,6 +6,8 @@
|
||||||
#if !defined _RNG_H_
|
#if !defined _RNG_H_
|
||||||
#define _RNG_H_
|
#define _RNG_H_
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct udevice;
|
struct udevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,7 +15,7 @@ if [ ${#dtc} -eq 0 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! which $dtc >/dev/null ; then
|
if ! which $dtc > /dev/null 2>&1 ; then
|
||||||
echo "Error: Cannot find dtc: $dtc"
|
echo "Error: Cannot find dtc: $dtc"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -544,7 +544,7 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
|
||||||
"bootmeth_script", 0, ofnode_null(), &dev));
|
"bootmeth_script", 0, ofnode_null(), &dev));
|
||||||
|
|
||||||
/* Enable the cros bootmeth if needed */
|
/* Enable the cros bootmeth if needed */
|
||||||
if (bind_cros) {
|
if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) {
|
||||||
ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
|
ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
|
||||||
ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
|
ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
|
||||||
"cros", 0, ofnode_null(), &dev));
|
"cros", 0, ofnode_null(), &dev));
|
||||||
|
|
|
@ -74,6 +74,9 @@ int bootstd_test_check_mmc_hunter(struct unit_test_state *uts)
|
||||||
struct bootstd_priv *std;
|
struct bootstd_priv *std;
|
||||||
uint seq;
|
uint seq;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_MMC))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* get access to the used hunters */
|
/* get access to the used hunters */
|
||||||
ut_assertok(bootstd_get_priv(&std));
|
ut_assertok(bootstd_get_priv(&std));
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,11 @@ static int mbr_test_run(struct unit_test_state *uts)
|
||||||
ut_assert(ofnode_valid(node));
|
ut_assert(ofnode_valid(node));
|
||||||
ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
|
ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
|
||||||
|
|
||||||
mbr_parts_max = sizeof('\0') + 2 +
|
/*
|
||||||
|
* 1 byte for null character
|
||||||
|
* 2 reserved bytes
|
||||||
|
*/
|
||||||
|
mbr_parts_max = 1 + 2 +
|
||||||
strlen(mbr_parts_header) +
|
strlen(mbr_parts_header) +
|
||||||
strlen(mbr_parts_p1) +
|
strlen(mbr_parts_p1) +
|
||||||
strlen(mbr_parts_p2) +
|
strlen(mbr_parts_p2) +
|
||||||
|
|
|
@ -179,6 +179,16 @@ static int setexpr_test_regex(struct unit_test_state *uts)
|
||||||
val = env_get("mary");
|
val = env_get("mary");
|
||||||
ut_asserteq_str("this is a test", val);
|
ut_asserteq_str("this is a test", val);
|
||||||
|
|
||||||
|
/* No match */
|
||||||
|
ut_assertok(run_command("setenv fred 'this is a test'", 0));
|
||||||
|
ut_assertok(run_command("setenv mary ''", 0));
|
||||||
|
ut_assertok(run_command("setexpr fred gsub us is \"${fred}\"", 0));
|
||||||
|
ut_assertok(run_command("setexpr mary gsub us is \"${fred}\"", 0));
|
||||||
|
val = env_get("fred");
|
||||||
|
ut_asserteq_str("this is a test", val);
|
||||||
|
val = env_get("mary");
|
||||||
|
ut_asserteq_str("this is a test", val);
|
||||||
|
|
||||||
unmap_sysmem(buf);
|
unmap_sysmem(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import pytest
|
||||||
import u_boot_utils
|
import u_boot_utils
|
||||||
import uuid
|
import uuid
|
||||||
import datetime
|
import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Note: This test relies on boardenv_* containing configuration values to define
|
Note: This test relies on boardenv_* containing configuration values to define
|
||||||
|
@ -31,6 +32,12 @@ env__net_uses_pci = True
|
||||||
# set to False.
|
# set to False.
|
||||||
env__net_dhcp_server = True
|
env__net_dhcp_server = True
|
||||||
|
|
||||||
|
# False or omitted if a DHCP server is attached to the network, and dhcp abort
|
||||||
|
# case should be tested.
|
||||||
|
# If DHCP abort testing is not possible or desired, set this variable to True.
|
||||||
|
# For example: On some setup, dhcp is too fast and this case may not work.
|
||||||
|
env__dhcp_abort_test_skip = True
|
||||||
|
|
||||||
# True if a DHCPv6 server is attached to the network, and should be tested.
|
# True if a DHCPv6 server is attached to the network, and should be tested.
|
||||||
# If DHCPv6 testing is not possible or desired, this variable may be omitted or
|
# If DHCPv6 testing is not possible or desired, this variable may be omitted or
|
||||||
# set to False.
|
# set to False.
|
||||||
|
@ -120,6 +127,57 @@ def test_net_dhcp(u_boot_console):
|
||||||
global net_set_up
|
global net_set_up
|
||||||
net_set_up = True
|
net_set_up = True
|
||||||
|
|
||||||
|
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||||
|
@pytest.mark.buildconfigspec('cmd_mii')
|
||||||
|
def test_net_dhcp_abort(u_boot_console):
|
||||||
|
"""Test the dhcp command by pressing ctrl+c in the middle of dhcp request
|
||||||
|
|
||||||
|
The boardenv_* file may be used to enable/disable this test; see the
|
||||||
|
comment at the beginning of this file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
|
||||||
|
if not test_dhcp:
|
||||||
|
pytest.skip('No DHCP server available')
|
||||||
|
|
||||||
|
if u_boot_console.config.env.get('env__dhcp_abort_test_skip', True):
|
||||||
|
pytest.skip('DHCP abort test is not enabled!')
|
||||||
|
|
||||||
|
u_boot_console.run_command('setenv autoload no')
|
||||||
|
|
||||||
|
# Phy reset before running dhcp command
|
||||||
|
output = u_boot_console.run_command('mii device')
|
||||||
|
if not re.search(r"Current device: '(.+?)'", output):
|
||||||
|
pytest.skip('PHY device does not exist!')
|
||||||
|
eth_num = re.search(r"Current device: '(.+?)'", output).groups()[0]
|
||||||
|
u_boot_console.run_command(f'mii device {eth_num}')
|
||||||
|
output = u_boot_console.run_command('mii info')
|
||||||
|
eth_addr = hex(int(re.search(r'PHY (.+?):', output).groups()[0], 16))
|
||||||
|
u_boot_console.run_command(f'mii modify {eth_addr} 0 0x8000 0x8000')
|
||||||
|
|
||||||
|
u_boot_console.run_command('dhcp', wait_for_prompt=False)
|
||||||
|
try:
|
||||||
|
u_boot_console.wait_for('Waiting for PHY auto negotiation to complete')
|
||||||
|
except:
|
||||||
|
pytest.skip('Timeout waiting for PHY auto negotiation to complete')
|
||||||
|
|
||||||
|
u_boot_console.wait_for('done')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Sending Ctrl-C
|
||||||
|
output = u_boot_console.run_command(
|
||||||
|
chr(3), wait_for_echo=False, send_nl=False
|
||||||
|
)
|
||||||
|
assert 'TIMEOUT' not in output
|
||||||
|
assert 'DHCP client bound to address ' not in output
|
||||||
|
assert 'Abort' in output
|
||||||
|
finally:
|
||||||
|
# Provide a time to recover from Abort - if it is not performed
|
||||||
|
# There is message like: ethernet@ff0e0000: No link.
|
||||||
|
u_boot_console.run_command('sleep 1')
|
||||||
|
# Run the dhcp test to setup the network configuration
|
||||||
|
test_net_dhcp(u_boot_console)
|
||||||
|
|
||||||
@pytest.mark.buildconfigspec('cmd_dhcp6')
|
@pytest.mark.buildconfigspec('cmd_dhcp6')
|
||||||
def test_net_dhcp6(u_boot_console):
|
def test_net_dhcp6(u_boot_console):
|
||||||
"""Test the dhcp6 command.
|
"""Test the dhcp6 command.
|
||||||
|
|
Loading…
Add table
Reference in a new issue