1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-13 03:41:54 +00:00

Update uboot for BPI-R2

This commit is contained in:
Ycarus (Yannick Chabanois) 2020-04-11 13:08:08 +02:00
parent a997f379a0
commit 1385e89bce
29 changed files with 134 additions and 3873 deletions

View file

@ -9,11 +9,11 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_VERSION:=2019.01
PKG_VERSION:=2020.04-rc5
PKG_HASH:=50bd7e5a466ab828914d080d5f6a432345b500e8fba1ad3b7b61e95e60d51c22
PKG_HASH:=1c967c90d3ab4fcc5817fbca4db8928311a8b3dfa9f827e9c585a590fd94ca7a
PKG_MAINTAINER:=Alexey Loukianov <lx2@lexa2.ru>
PKG_MAINTAINER:=Cristian Ciobanu <cioby.service@gmail.com>
include $(INCLUDE_DIR)/u-boot.mk
include $(INCLUDE_DIR)/package.mk
@ -28,7 +28,7 @@ endef
define U-Boot/mt7623n_bpir2
BUILD_SUBTARGET:=mt7623
NAME:=Bannana PI R2 (mt7623)
BUILD_DEVICES:=7623n-bananapi-bpi-r2
BUILD_DEVICES:=bpi_bananapi-r2
endef
UBOOT_TARGETS := \
@ -43,7 +43,7 @@ UBOOT_MAKE_FLAGS = \
define Build/Prepare
$(call Build/Prepare/Default)
$(CP) uEnv-$(UENV).txt $(PKG_BUILD_DIR)/uEnv.txt
$(CP) uEnv-$(UENV).txt ${PKG_BUILD_DIR}/uEnv.txt
endef
define Build/InstallDev

View file

@ -0,0 +1,64 @@
From 075db54b57761868cd63434b466fffe7ba7a564f Mon Sep 17 00:00:00 2001
From: Cristian Ciobanu <cioby.service@gmail.com>
Date: Thu, 9 Apr 2020 17:59:27 +0300
Subject: [PATCH] defconfig: r2: Add additional U-boot options for mt7623n
---
configs/mt7623n_bpir2_defconfig | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index 07ddade76a..36a903cbe7 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -3,7 +3,7 @@ CONFIG_SYS_THUMB_BUILD=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_SYS_TEXT_BASE=0x81e00000
CONFIG_SYS_MALLOC_F_LEN=0x4000
-CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0x100000
CONFIG_TARGET_MT7623=y
CONFIG_NR_DRAM_BANKS=1
@@ -14,7 +14,7 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_DEFAULT_FDT_FILE="mt7623n-bananapi-bpi-r2"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_SYS_PROMPT="BPI-R2> "
CONFIG_CMD_BOOTMENU=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
@@ -57,3 +57,29 @@ CONFIG_MTK_TIMER=y
CONFIG_WDT_MTK=y
CONFIG_LZMA=y
# CONFIG_EFI_LOADER is not set
+
+CONFIG_LOCALVERSION_AUTO=n
+CONFIG_USE_DEFAULT_ENV_FILE=y
+CONFIG_DEFAULT_ENV_FILE="uEnv.txt"
+CONFIG_CMD_BOOTZ=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+
+#commands used in uenv.txt
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_STRINGS=y
+CONFIG_CMD_SETEXPR=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCIE_MEDIATEK=y
+CONFIG_PHY=y
+CONFIG_PHY_MTK_TPHY=y
+CONFIG_CMD_PCI=y
+CONFIG_AHCI=y
+CONFIG_AHCI_PCI=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
+CONFIG_SCSI_AHCI=y
+CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_POWER_MT6323=y
--
2.25.1

View file

@ -1,39 +0,0 @@
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index ae4fb280..74252cd0 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -3,6 +3,7 @@ CONFIG_SYS_THUMB_BUILD=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_SYS_TEXT_BASE=0x81e00000
CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_TARGET_MT7623=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
@@ -11,7 +12,7 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_DEFAULT_FDT_FILE="mt7623n-bananapi-bpi-r2"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="U-Boot> "
+CONFIG_SYS_PROMPT="BPI-R2> "
CONFIG_CMD_BOOTMENU=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
@@ -51,3 +52,14 @@ CONFIG_MTK_TIMER=y
CONFIG_WDT_MTK=y
CONFIG_LZMA=y
# CONFIG_EFI_LOADER is not set
+
+CONFIG_CMD_BOOTZ=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+
+CONFIG_USE_DEFAULT_ENV_FILE=y
+CONFIG_DEFAULT_ENV_FILE="uEnv.txt"
+
+#enables savenenv-command
+CONFIG_ENV_IS_IN_MMC=y
+
+CONFIG_CMD_ASKENV=y
--
1.8.3.1

View file

@ -1,61 +0,0 @@
From 2a59134ba1d841cf1a7845017656b74b74412aaf Mon Sep 17 00:00:00 2001
From: Frank Wunderlich <frank-w@public-files.de>
Date: Mon, 3 Dec 2018 15:32:58 +0100
Subject: adding saveenv-command for bananapi r2
bananapi r2 can be booted from sd-card and emmc
saving the environment have to choose the storage
from which the device has booted
also the offset is set to 1MB-50Kb to make sure env is written
to block "user data area" between uboot and first partition
https://www.fw-web.de/dokuwiki/lib/exe/fetch.php?cache=&media=bpi-r2:boot-structure.png
v3: removed changes in defconfig (users choice)
v2: fixed bracket-style in if-else statement
Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
diff --git a/board/mediatek/mt7623/mt7623_rfb.c b/board/mediatek/mt7623/mt7623_rfb.c
index 08468b50..4ec27649 100644
--- a/board/mediatek/mt7623/mt7623_rfb.c
+++ b/board/mediatek/mt7623/mt7623_rfb.c
@@ -14,3 +14,22 @@ int board_init(void)
return 0;
}
+
+int mmc_get_boot_dev(void)
+{
+ int g_mmc_devid = -1;
+ char *uflag = (char *)0x81DFFFF0;
+ if (strncmp(uflag,"eMMC",4)==0) {
+ g_mmc_devid = 0;
+ printf("Boot From Emmc(id:%d)\n\n", g_mmc_devid);
+ } else {
+ g_mmc_devid = 1;
+ printf("Boot From SD(id:%d)\n\n", g_mmc_devid);
+ }
+ return g_mmc_devid;
+}
+
+int mmc_get_env_dev(void)
+{
+ return mmc_get_boot_dev();
+}
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
index ba763501..fb6ac073 100644
--- a/include/configs/mt7623.h
+++ b/include/configs/mt7623.h
@@ -53,4 +53,7 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
FDT_HIGH
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_OFFSET 0xF3800
+
#endif
--
1.8.3.1

View file

@ -0,0 +1,23 @@
From 15e032f5b06ba97a7777bc32aef15e10d0086041 Mon Sep 17 00:00:00 2001
From: Cristian Ciobanu <cioby.service@gmail.com>
Date: Wed, 8 Apr 2020 22:27:01 +0300
Subject: [PATCH] u-boot: Modify environment offset for mt7623
---
include/configs/mt7623.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
index faab0913fc..5d0da71ce9 100644
--- a/include/configs/mt7623.h
+++ b/include/configs/mt7623.h
@@ -56,5 +56,6 @@
#define CONFIG_SERVERIP 192.168.1.2
#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_OFFSET 0xF3800
#endif
--
2.25.1

View file

@ -1,14 +1,17 @@
From 17843557032cc342117591939483d238e80bd169 Mon Sep 17 00:00:00 2001
From 798f0fc54926093a074a9cbb011de833a0614c3a Mon Sep 17 00:00:00 2001
From: Frank Wunderlich <frank-w@public-files.de>
Date: Fri, 28 Dec 2018 17:56:19 +0100
Subject: [bootmenu] added key-input (1-9,a-f)
Subject: [PATCH 1/2] bootmenu: added key-input (1-9,a-f)
---
cmd/bootmenu.c | 145 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 94 insertions(+), 51 deletions(-)
diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index 7f88c1ed..0935fd40 100644
index 3dc2c854ac..fd6ba6c8af 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -39,7 +39,22 @@ struct bootmenu_data {
@@ -40,7 +40,22 @@ struct bootmenu_data {
enum bootmenu_key {
KEY_NONE = 0,
@ -32,7 +35,7 @@ index 7f88c1ed..0935fd40 100644
KEY_DOWN,
KEY_SELECT,
};
@@ -77,6 +92,23 @@ static void bootmenu_print_entry(void *data)
@@ -78,6 +93,23 @@ static void bootmenu_print_entry(void *data)
puts(ANSI_COLOR_RESET);
}
@ -56,7 +59,7 @@ index 7f88c1ed..0935fd40 100644
static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
enum bootmenu_key *key, int *esc)
{
@@ -97,23 +129,23 @@ static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
@@ -98,23 +130,23 @@ static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
menu->delay = -1;
c = getc();
@ -94,7 +97,7 @@ index 7f88c1ed..0935fd40 100644
if (menu->delay < 0)
break;
@@ -140,47 +172,49 @@ static void bootmenu_loop(struct bootmenu_data *menu,
@@ -141,47 +173,49 @@ static void bootmenu_loop(struct bootmenu_data *menu,
c = getc();
@ -179,7 +182,7 @@ index 7f88c1ed..0935fd40 100644
/* enter key was pressed */
if (c == '\r')
*key = KEY_SELECT;
@@ -203,6 +237,14 @@ static char *bootmenu_choice_entry(void *data)
@@ -204,6 +238,14 @@ static char *bootmenu_choice_entry(void *data)
bootmenu_loop(menu, &key, &esc);
}
@ -194,7 +197,7 @@ index 7f88c1ed..0935fd40 100644
switch (key) {
case KEY_UP:
if (menu->active > 0)
@@ -222,6 +264,7 @@ static char *bootmenu_choice_entry(void *data)
@@ -223,6 +265,7 @@ static char *bootmenu_choice_entry(void *data)
default:
break;
}
@ -202,7 +205,7 @@ index 7f88c1ed..0935fd40 100644
}
/* never happens */
@@ -466,7 +509,7 @@ void menu_display_statusline(struct menu *m)
@@ -467,7 +510,7 @@ void menu_display_statusline(struct menu *m)
printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
puts(ANSI_CLEAR_LINE);
printf(ANSI_CURSOR_POSITION, menu->count + 6, 1);
@ -212,5 +215,5 @@ index 7f88c1ed..0935fd40 100644
printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
puts(ANSI_CLEAR_LINE);
--
1.8.3.1
2.25.1

View file

@ -1,189 +0,0 @@
From e4033f535d7f6f86f354d36037565a319c02c324 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:51 +0800
Subject: reset: MedaiTek: add reset controller driver for MediaTek SoCs
This patch adds reset controller driver for MediaTek SoCs.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
diff --git a/arch/arm/include/asm/arch-mediatek/reset.h b/arch/arm/include/asm/arch-mediatek/reset.h
new file mode 100644
index 00000000..9704666d
--- /dev/null
+++ b/arch/arm/include/asm/arch-mediatek/reset.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef __MEDIATEK_RESET_H
+#define __MEDIATEK_RESET_H
+
+#include <dm.h>
+
+int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs);
+
+#endif /* __MEDIATEK_RESET_H */
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 9c5208b7..3a6d61f4 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -106,4 +106,11 @@ config RESET_SOCFPGA
help
Support for reset controller on SoCFPGA platform.
+config RESET_MEDIATEK
+ bool "Reset controller driver for MediaTek SoCs"
+ depends on DM_RESET && ARCH_MEDIATEK && CLK
+ default y
+ help
+ Support for reset controller on MediaTek SoCs.
+
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f4520878..8a4dcab8 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o
diff --git a/drivers/reset/reset-mediatek.c b/drivers/reset/reset-mediatek.c
new file mode 100644
index 00000000..e3614e6e
--- /dev/null
+++ b/drivers/reset/reset-mediatek.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ * Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+
+struct mediatek_reset_priv {
+ struct regmap *regmap;
+ u32 regofs;
+ u32 nr_resets;
+};
+
+static int mediatek_reset_request(struct reset_ctl *reset_ctl)
+{
+ return 0;
+}
+
+static int mediatek_reset_free(struct reset_ctl *reset_ctl)
+{
+ return 0;
+}
+
+static int mediatek_reset_assert(struct reset_ctl *reset_ctl)
+{
+ struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ int id = reset_ctl->id;
+
+ if (id >= priv->nr_resets)
+ return -EINVAL;
+
+ return regmap_update_bits(priv->regmap,
+ priv->regofs + ((id / 32) << 2), BIT(id % 32), BIT(id % 32));
+}
+
+static int mediatek_reset_deassert(struct reset_ctl *reset_ctl)
+{
+ struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ int id = reset_ctl->id;
+
+ if (id >= priv->nr_resets)
+ return -EINVAL;
+
+ return regmap_update_bits(priv->regmap,
+ priv->regofs + ((id / 32) << 2), BIT(id % 32), 0);
+}
+
+struct reset_ops mediatek_reset_ops = {
+ .request = mediatek_reset_request,
+ .free = mediatek_reset_free,
+ .rst_assert = mediatek_reset_assert,
+ .rst_deassert = mediatek_reset_deassert,
+};
+
+static int mediatek_reset_probe(struct udevice *dev)
+{
+ struct mediatek_reset_priv *priv = dev_get_priv(dev);
+
+ if (!priv->regofs && !priv->nr_resets)
+ return -EINVAL;
+
+ priv->regmap = syscon_node_to_regmap(dev_ofnode(dev));
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ return 0;
+}
+
+int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs)
+{
+ struct udevice *rst_dev;
+ struct mediatek_reset_priv *priv;
+ int ret;
+
+ ret = device_bind_driver_to_node(pdev, "mediatek_reset", "reset",
+ dev_ofnode(pdev), &rst_dev);
+ if (ret)
+ return ret;
+
+ priv = malloc(sizeof(struct mediatek_reset_priv));
+ priv->regofs = regofs;
+ priv->nr_resets = num_regs * 32;
+ rst_dev->priv = priv;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(mediatek_reset) = {
+ .name = "mediatek_reset",
+ .id = UCLASS_RESET,
+ .probe = mediatek_reset_probe,
+ .ops = &mediatek_reset_ops,
+ .priv_auto_alloc_size = sizeof(struct mediatek_reset_priv),
+};
diff --git a/include/dt-bindings/reset/mtk-reset.h b/include/dt-bindings/reset/mtk-reset.h
new file mode 100644
index 00000000..5f0a74f2
--- /dev/null
+++ b/include/dt-bindings/reset/mtk-reset.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ */
+
+#ifndef _DT_BINDINGS_MTK_RESET_H_
+#define _DT_BINDINGS_MTK_RESET_H_
+
+/* ETHSYS */
+#define ETHSYS_PPE_RST 31
+#define ETHSYS_EPHY_RST 24
+#define ETHSYS_GMAC_RST 23
+#define ETHSYS_ESW_RST 16
+#define ETHSYS_FE_RST 6
+#define ETHSYS_MCM_RST 2
+#define ETHSYS_SYS_RST 0
+
+#endif /* _DT_BINDINGS_MTK_RESET_H_ */
--
1.8.3.1

View file

@ -0,0 +1,25 @@
From 39b0c824b56be1000844cedb5faba506b6b09b9b Mon Sep 17 00:00:00 2001
From: Cristian Ciobanu <cioby.service@gmail.com>
Date: Fri, 10 Apr 2020 00:41:42 +0300
Subject: [PATCH] Add EXT4 support in U-boot
---
configs/mt7623n_bpir2_defconfig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index 36a903cbe7..09b9b6f797 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -83,3 +83,8 @@ CONFIG_DM_SCSI=y
CONFIG_SCSI_AHCI=y
CONFIG_HAVE_BLOCK_DEVICE=y
CONFIG_POWER_MT6323=y
+
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_FS_EXT4=y
+CONFIG_EXT4_WRITE=y
--
2.25.1

View file

@ -1,109 +0,0 @@
From ab7ad2d077ef18d6d853c8838bc116fbbd0ac154 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:52 +0800
Subject: clk: MediaTek: bind ethsys reset controller
The ethsys contains not only the clock gating controller, but also the
reset controller for the whole ethernet subsystem and its components.
This patch adds binding of the reset controller so that the ethernet node
can have references on it.
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
index c6b09d8e..87ad4f79 100644
--- a/drivers/clk/mediatek/clk-mt7623.c
+++ b/drivers/clk/mediatek/clk-mt7623.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
+#include <asm/arch-mediatek/reset.h>
#include <asm/io.h>
#include <dt-bindings/clock/mt7623-clk.h>
@@ -782,6 +783,19 @@ static int mt7623_ethsys_probe(struct udevice *dev)
return mtk_common_clk_gate_init(dev, &mt7623_clk_tree, eth_cgs);
}
+static int mt7623_ethsys_bind(struct udevice *dev)
+{
+ int ret = 0;
+
+#if CONFIG_IS_ENABLED(RESET_MEDIATEK)
+ ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1);
+ if (ret)
+ debug("Warning: failed to bind ethsys reset controller\n");
+#endif
+
+ return ret;
+}
+
static const struct udevice_id mt7623_apmixed_compat[] = {
{ .compatible = "mediatek,mt7623-apmixedsys" },
{ }
@@ -865,6 +879,7 @@ U_BOOT_DRIVER(mtk_clk_ethsys) = {
.id = UCLASS_CLK,
.of_match = mt7623_ethsys_compat,
.probe = mt7623_ethsys_probe,
+ .bind = mt7623_ethsys_bind,
.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
.ops = &mtk_clk_gate_ops,
};
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
index 2601b6cf..6a9f6013 100644
--- a/drivers/clk/mediatek/clk-mt7629.c
+++ b/drivers/clk/mediatek/clk-mt7629.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
+#include <asm/arch-mediatek/reset.h>
#include <asm/io.h>
#include <dt-bindings/clock/mt7629-clk.h>
@@ -602,6 +603,19 @@ static int mt7629_ethsys_probe(struct udevice *dev)
return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs);
}
+static int mt7629_ethsys_bind(struct udevice *dev)
+{
+ int ret = 0;
+
+#if CONFIG_IS_ENABLED(RESET_MEDIATEK)
+ ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1);
+ if (ret)
+ debug("Warning: failed to bind ethsys reset controller\n");
+#endif
+
+ return ret;
+}
+
static int mt7629_sgmiisys_probe(struct udevice *dev)
{
return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs);
@@ -695,6 +709,7 @@ U_BOOT_DRIVER(mtk_clk_ethsys) = {
.id = UCLASS_CLK,
.of_match = mt7629_ethsys_compat,
.probe = mt7629_ethsys_probe,
+ .bind = mt7629_ethsys_bind,
.priv_auto_alloc_size = sizeof(struct mtk_cg_priv),
.ops = &mtk_clk_gate_ops,
};
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 74152ed9..7847388b 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -23,6 +23,8 @@
#define CLK_PARENT_TOPCKGEN BIT(5)
#define CLK_PARENT_MASK GENMASK(5, 4)
+#define ETHSYS_RST_CTRL_OFS 0x34
+
/* struct mtk_pll_data - hardware-specific PLLs data */
struct mtk_pll_data {
const int id;
--
1.8.3.1

View file

@ -1,76 +0,0 @@
From fbdf1c37235d4a5a50eaafff41cacff4fd3a6e9f Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:54 +0800
Subject: arm: dts: add ethernet related node for MT7623 SoC
This patch adds ethernet gmac node for MT7623 with MT7530 gigabit switch.
Signed-off-by: Mark Lee <Mark-MC.Lee@mediatek.com>
diff --git a/arch/arm/dts/mt7623.dtsi b/arch/arm/dts/mt7623.dtsi
index f50f4ef1..448d1d73 100644
--- a/arch/arm/dts/mt7623.dtsi
+++ b/arch/arm/dts/mt7623.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/mt7623-power.h>
+#include <dt-bindings/reset/mtk-reset.h>
#include "skeleton.dtsi"
/ {
@@ -248,8 +249,26 @@
};
ethsys: syscon@1b000000 {
- compatible = "mediatek,mt7623-ethsys";
+ compatible = "mediatek,mt7623-ethsys", "syscon";
reg = <0x1b000000 0x1000>;
#clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ eth: ethernet@1b100000 {
+ compatible = "mediatek,mt7623-eth", "syscon";
+ reg = <0x1b100000 0x20000>;
+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
+ <&ethsys CLK_ETHSYS_ESW>,
+ <&ethsys CLK_ETHSYS_GP1>,
+ <&ethsys CLK_ETHSYS_GP2>,
+ <&apmixedsys CLK_APMIXED_TRGPLL>;
+ clock-names = "ethif", "esw", "gp1", "gp2", "trgpll";
+ power-domains = <&scpsys MT7623_POWER_DOMAIN_ETH>;
+ resets = <&ethsys ETHSYS_FE_RST>,
+ <&ethsys ETHSYS_MCM_RST>;
+ reset-names = "fe", "mcm";
+ mediatek,ethsys = <&ethsys>;
+ status = "disabled";
};
};
diff --git a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
index 84a77fde..51628bb6 100644
--- a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
+++ b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts
@@ -67,6 +67,19 @@
};
};
+&eth {
+ status = "okay";
+ mediatek,gmac-id = <0>;
+ phy-mode = "rgmii";
+ mediatek,switch = "mt7530";
+ reset-gpios = <&gpio 33 GPIO_ACTIVE_HIGH>;
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_default>;
--
1.8.3.1

View file

@ -1,95 +0,0 @@
From 038e3dc3801007f5025a2e57bb4b715c48b9590d Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:55 +0800
Subject: arm: dts: add ethernet related node for MT7629 SoC
This patch adds ethernet gmac node for MT7629 with internal gigabit phy.
Signed-off-by: Mark Lee <Mark-MC.Lee@mediatek.com>
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
index a6d28a06..95d10aa6 100644
--- a/arch/arm/dts/mt7629-rfb.dts
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -22,6 +22,17 @@
};
};
+&eth {
+ status = "okay";
+ mediatek,gmac-id = <1>;
+ phy-mode = "gmii";
+ phy-handle = <&phy0>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
&pinctrl {
qspi_pins: qspi-pins {
mux {
diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi
index e6052bbd..c87115e0 100644
--- a/arch/arm/dts/mt7629.dtsi
+++ b/arch/arm/dts/mt7629.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/mt7629-power.h>
+#include <dt-bindings/reset/mtk-reset.h>
#include "skeleton.dtsi"
/ {
@@ -228,6 +229,48 @@
compatible = "mediatek,mt7629-ethsys", "syscon";
reg = <0x1b000000 0x1000>;
#clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ eth: ethernet@1b100000 {
+ compatible = "mediatek,mt7629-eth", "syscon";
+ reg = <0x1b100000 0x20000>;
+ clocks = <&topckgen CLK_TOP_ETH_SEL>,
+ <&topckgen CLK_TOP_F10M_REF_SEL>,
+ <&ethsys CLK_ETH_ESW_EN>,
+ <&ethsys CLK_ETH_GP0_EN>,
+ <&ethsys CLK_ETH_GP1_EN>,
+ <&ethsys CLK_ETH_GP2_EN>,
+ <&ethsys CLK_ETH_FE_EN>,
+ <&sgmiisys0 CLK_SGMII_TX_EN>,
+ <&sgmiisys0 CLK_SGMII_RX_EN>,
+ <&sgmiisys0 CLK_SGMII_CDR_REF>,
+ <&sgmiisys0 CLK_SGMII_CDR_FB>,
+ <&sgmiisys1 CLK_SGMII_TX_EN>,
+ <&sgmiisys1 CLK_SGMII_RX_EN>,
+ <&sgmiisys1 CLK_SGMII_CDR_REF>,
+ <&sgmiisys1 CLK_SGMII_CDR_FB>,
+ <&apmixedsys CLK_APMIXED_SGMIPLL>,
+ <&apmixedsys CLK_APMIXED_ETH2PLL>;
+ clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2",
+ "fe", "sgmii_tx250m", "sgmii_rx250m",
+ "sgmii_cdr_ref", "sgmii_cdr_fb",
+ "sgmii2_tx250m", "sgmii2_rx250m",
+ "sgmii2_cdr_ref", "sgmii2_cdr_fb",
+ "sgmii_ck", "eth2pll";
+ assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>,
+ <&topckgen CLK_TOP_F10M_REF_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>,
+ <&topckgen CLK_TOP_SGMIIPLL_D2>;
+ power-domains = <&scpsys MT7629_POWER_DOMAIN_ETHSYS>;
+ resets = <&ethsys ETHSYS_FE_RST>;
+ reset-names = "fe";
+ mediatek,ethsys = <&ethsys>;
+ mediatek,sgmiisys = <&sgmiisys0>;
+ mediatek,infracfg = <&infracfg>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
sgmiisys0: syscon@1b128000 {
--
1.8.3.1

View file

@ -1,59 +0,0 @@
From 8da1e0fd083f4c6a71f6735c06698e71250bcc07 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:56 +0800
Subject: arm: MediaTek: add ethernet support for MT7623 boards
Enable ethernet related configs to mt7623n_bpir2_defconfig.
Add default IP addresses.
Enable noncached memory region required by ethernet driver.
Signed-off-by: Mark Lee <Mark-MC.Lee@mediatek.com>
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index 74252cd0..bb67f328 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -29,6 +29,7 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2"
+CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
# CONFIG_BLOCK_CACHE is not set
@@ -38,6 +39,11 @@ CONFIG_DM_MMC=y
# CONFIG_MMC_QUIRKS is not set
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_MTK=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_MEDIATEK=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_PINCTRL_MT7623=y
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
index fb6ac073..7d26debb 100644
--- a/include/configs/mt7623.h
+++ b/include/configs/mt7623.h
@@ -24,6 +24,7 @@
/* Size of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN SZ_4M
+#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M
/* Environment */
#define CONFIG_ENV_SIZE SZ_4K
@@ -56,4 +57,8 @@
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_ENV_OFFSET 0x100000
+/* Ethernet */
+#define CONFIG_IPADDR 192.168.1.1
+#define CONFIG_SERVERIP 192.168.1.2
+
#endif
--
1.8.3.1

View file

@ -1,58 +0,0 @@
From 0fcb7ab842170e1ea7e9bf4d309af584b1e54388 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:57 +0800
Subject: arm: MediaTek: add ethernet support for MT7629 boards
Enable ethernet related configs to mt7629_rfb_defconfig.
Add default IP addresses.
Enable noncached memory region required by ethernet driver.
Signed-off-by: Mark Lee <Mark-MC.Lee@mediatek.com>
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
index 1729d13c..fdd5f575 100644
--- a/configs/mt7629_rfb_defconfig
+++ b/configs/mt7629_rfb_defconfig
@@ -32,6 +32,7 @@ CONFIG_CMD_PING=y
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents"
+CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM_SEQ_ALIAS=y
CONFIG_REGMAP=y
CONFIG_SPL_REGMAP=y
@@ -51,6 +52,10 @@ CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_MEDIATEK=y
+CONFIG_DM_ETH=y
+CONFIG_MEDIATEK_ETH=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_PINCTRL_MT7629=y
diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h
index a665a5eb..9910d8c8 100644
--- a/include/configs/mt7629.h
+++ b/include/configs/mt7629.h
@@ -24,6 +24,7 @@
/* Size of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN SZ_4M
+#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M
/* Environment */
#define CONFIG_ENV_SIZE SZ_4K
@@ -54,4 +55,8 @@
/* DRAM */
#define CONFIG_SYS_SDRAM_BASE 0x40000000
+/* Ethernet */
+#define CONFIG_IPADDR 192.168.1.1
+#define CONFIG_SERVERIP 192.168.1.2
+
#endif
--
1.8.3.1

View file

@ -1,25 +0,0 @@
From 31ca82655b5f623303e45508a820205b071df258 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:58 +0800
Subject: MAINTAINERS: ARM MEDIATEK: update file entries
This patch adds new file entries for MediaTek SoCs
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index f86fdf9c..e192db07 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -176,6 +176,8 @@ F: drivers/ram/mediatek/
F: drivers/spi/mtk_qspi.c
F: drivers/timer/mtk_timer.c
F: drivers/watchdog/mtk_wdt.c
+F: drivers/net/mtk_eth.c
+F: drivers/reset/reset-mediatek.c
F: tools/mtk_image.c
F: tools/mtk_image.h
N: mediatek
--
1.8.3.1

View file

@ -1,40 +0,0 @@
From d4b93c443372d651bd6f8b78070c54338ee35b91 Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Thu, 20 Dec 2018 16:12:59 +0800
Subject: configs: MediaTek: use OF_SEPARATE instead of OF_EMBED
This patch replace OF_EMBED with OF_SEPARATE of defconfig files of
MediaTek boards because now OF_EMBED is only used for debugging purpose.
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index bb67f328..a9f4506e 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -27,7 +27,7 @@ CONFIG_CMD_READ=y
CONFIG_CMD_PING=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
-CONFIG_OF_EMBED=y
+CONFIG_OF_SEPARATE=y
CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2"
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_REGMAP=y
diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig
index fdd5f575..1da9932d 100644
--- a/configs/mt7629_rfb_defconfig
+++ b/configs/mt7629_rfb_defconfig
@@ -29,7 +29,7 @@ CONFIG_CMD_SF_TEST=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_PING=y
# CONFIG_PARTITIONS is not set
-CONFIG_OF_EMBED=y
+CONFIG_OF_SEPARATE=y
CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb"
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents"
CONFIG_NET_RANDOM_ETHADDR=y
--
1.8.3.1

View file

@ -1,326 +0,0 @@
From d6755b9b0e59ea0193914e169f74df51d556fbb7 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:14 +0100
Subject: test: add test for lib/lmb.c
Add basic tests for the lmb memory allocation code used to reserve and
allocate memory during boot.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/test/lib/Makefile b/test/lib/Makefile
index ea68fae5..5a636aac 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -3,3 +3,4 @@
# (C) Copyright 2018
# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
obj-y += hexdump.o
+obj-y += lmb.o
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
new file mode 100644
index 00000000..dd7ba14b
--- /dev/null
+++ b/test/lib/lmb.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Simon Goldschmidt
+ */
+
+#include <common.h>
+#include <lmb.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+static int check_lmb(struct unit_test_state *uts, struct lmb *lmb,
+ phys_addr_t ram_base, phys_size_t ram_size,
+ unsigned long num_reserved,
+ phys_addr_t base1, phys_size_t size1,
+ phys_addr_t base2, phys_size_t size2,
+ phys_addr_t base3, phys_size_t size3)
+{
+ ut_asserteq(lmb->memory.cnt, 1);
+ ut_asserteq(lmb->memory.region[0].base, ram_base);
+ ut_asserteq(lmb->memory.region[0].size, ram_size);
+
+ ut_asserteq(lmb->reserved.cnt, num_reserved);
+ if (num_reserved > 0) {
+ ut_asserteq(lmb->reserved.region[0].base, base1);
+ ut_asserteq(lmb->reserved.region[0].size, size1);
+ }
+ if (num_reserved > 1) {
+ ut_asserteq(lmb->reserved.region[1].base, base2);
+ ut_asserteq(lmb->reserved.region[1].size, size2);
+ }
+ if (num_reserved > 2) {
+ ut_asserteq(lmb->reserved.region[2].base, base3);
+ ut_asserteq(lmb->reserved.region[2].size, size3);
+ }
+ return 0;
+}
+
+#define ASSERT_LMB(lmb, ram_base, ram_size, num_reserved, base1, size1, \
+ base2, size2, base3, size3) \
+ ut_assert(!check_lmb(uts, lmb, ram_base, ram_size, \
+ num_reserved, base1, size1, base2, size2, base3, \
+ size3))
+
+/*
+ * Test helper function that reserves 64 KiB somewhere in the simulated RAM and
+ * then does some alloc + free tests.
+ */
+static int test_multi_alloc(struct unit_test_state *uts,
+ const phys_addr_t ram, const phys_size_t ram_size,
+ const phys_addr_t alloc_64k_addr)
+{
+ const phys_addr_t ram_end = ram + ram_size;
+ const phys_addr_t alloc_64k_end = alloc_64k_addr + 0x10000;
+
+ struct lmb lmb;
+ long ret;
+ phys_addr_t a, a2, b, b2, c, d;
+
+ /* check for overflow */
+ ut_assert(ram_end == 0 || ram_end > ram);
+ ut_assert(alloc_64k_end > alloc_64k_addr);
+ /* check input addresses + size */
+ ut_assert(alloc_64k_addr >= ram + 8);
+ ut_assert(alloc_64k_end <= ram_end - 8);
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* reserve 64KiB somewhere */
+ ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+ 0, 0, 0, 0);
+
+ /* allocate somewhere, should be at the end of RAM */
+ a = lmb_alloc(&lmb, 4, 1);
+ ut_asserteq(a, ram_end - 4);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, alloc_64k_addr, 0x10000,
+ ram_end - 4, 4, 0, 0);
+ /* alloc below end of reserved region -> below reserved region */
+ b = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+ ut_asserteq(b, alloc_64k_addr - 4);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 4, 0x10000 + 4, ram_end - 4, 4, 0, 0);
+
+ /* 2nd time */
+ c = lmb_alloc(&lmb, 4, 1);
+ ut_asserteq(c, ram_end - 8);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 4, 0x10000 + 4, ram_end - 8, 8, 0, 0);
+ d = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+ ut_asserteq(d, alloc_64k_addr - 8);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
+
+ ret = lmb_free(&lmb, a, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+ /* allocate again to ensure we get the same address */
+ a2 = lmb_alloc(&lmb, 4, 1);
+ ut_asserteq(a, a2);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0);
+ ret = lmb_free(&lmb, a2, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+
+ ret = lmb_free(&lmb, b, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 3,
+ alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
+ ram_end - 8, 4);
+ /* allocate again to ensure we get the same address */
+ b2 = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end);
+ ut_asserteq(b, b2);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0);
+ ret = lmb_free(&lmb, b2, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 3,
+ alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000,
+ ram_end - 8, 4);
+
+ ret = lmb_free(&lmb, c, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 2,
+ alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, 0, 0);
+ ret = lmb_free(&lmb, d, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+ 0, 0, 0, 0);
+
+ return 0;
+}
+
+static int test_multi_alloc_512mb(struct unit_test_state *uts,
+ const phys_addr_t ram)
+{
+ return test_multi_alloc(uts, ram, 0x20000000, ram + 0x10000000);
+}
+
+/* Create a memory region with one reserved region and allocate */
+static int lib_test_lmb_simple(struct unit_test_state *uts)
+{
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ return test_multi_alloc_512mb(uts, 0x40000000);
+}
+
+DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
+static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
+{
+ const phys_size_t ram_size = 0x20000000;
+ const phys_size_t big_block_size = 0x10000000;
+ const phys_addr_t ram_end = ram + ram_size;
+ const phys_addr_t alloc_64k_addr = ram + 0x10000000;
+ struct lmb lmb;
+ long ret;
+ phys_addr_t a, b;
+
+ /* check for overflow */
+ ut_assert(ram_end == 0 || ram_end > ram);
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* reserve 64KiB in the middle of RAM */
+ ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+ 0, 0, 0, 0);
+
+ /* allocate a big block, should be below reserved */
+ a = lmb_alloc(&lmb, big_block_size, 1);
+ ut_asserteq(a, ram);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, a,
+ big_block_size + 0x10000, 0, 0, 0, 0);
+ /* allocate 2nd big block */
+ /* This should fail, printing an error */
+ b = lmb_alloc(&lmb, big_block_size, 1);
+ ut_asserteq(b, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, a,
+ big_block_size + 0x10000, 0, 0, 0, 0);
+
+ ret = lmb_free(&lmb, a, big_block_size);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+ 0, 0, 0, 0);
+
+ /* allocate too big block */
+ /* This should fail, printing an error */
+ a = lmb_alloc(&lmb, ram_size, 1);
+ ut_asserteq(a, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000,
+ 0, 0, 0, 0);
+
+ return 0;
+}
+
+static int lib_test_lmb_big(struct unit_test_state *uts)
+{
+ return test_bigblock(uts, 0x40000000);
+}
+
+DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, allocate a block without previous reservation */
+static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram)
+{
+ const phys_size_t ram_size = 0x20000000;
+ const phys_addr_t ram_end = ram + ram_size;
+ struct lmb lmb;
+ long ret;
+ phys_addr_t a, b;
+
+ /* check for overflow */
+ ut_assert(ram_end == 0 || ram_end > ram);
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* allocate a block */
+ a = lmb_alloc(&lmb, 4, 1);
+ ut_assert(a != 0);
+ /* and free it */
+ ret = lmb_free(&lmb, a, 4);
+ ut_asserteq(ret, 0);
+
+ /* allocate a block with base*/
+ b = lmb_alloc_base(&lmb, 4, 1, ram_end);
+ ut_assert(a == b);
+ /* and free it */
+ ret = lmb_free(&lmb, b, 4);
+ ut_asserteq(ret, 0);
+
+ return 0;
+}
+
+static int lib_test_lmb_noreserved(struct unit_test_state *uts)
+{
+ return test_noreserved(uts, 0x40000000);
+}
+
+DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/*
+ * Simulate a RAM that starts at 0 and allocate down to address 0, which must
+ * fail as '0' means failure for the lmb_alloc functions.
+ */
+static int lib_test_lmb_at_0(struct unit_test_state *uts)
+{
+ const phys_addr_t ram = 0;
+ const phys_size_t ram_size = 0x20000000;
+ struct lmb lmb;
+ long ret;
+ phys_addr_t a, b;
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* allocate nearly everything */
+ a = lmb_alloc(&lmb, ram_size - 4, 1);
+ ut_asserteq(a, ram + 4);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+ 0, 0, 0, 0);
+ /* allocate the rest */
+ /* This should fail as the allocated address would be 0 */
+ b = lmb_alloc(&lmb, 4, 1);
+ ut_asserteq(b, 0);
+ /* check that this was an error by checking lmb */
+ ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+ 0, 0, 0, 0);
+ /* check that this was an error by freeing b */
+ ret = lmb_free(&lmb, b, 4);
+ ut_asserteq(ret, -1);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4,
+ 0, 0, 0, 0);
+
+ ret = lmb_free(&lmb, a, ram_size - 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
+
+ return 0;
+}
+
+DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
1.8.3.1

View file

@ -1,157 +0,0 @@
From 8d8854693b9a288c6dbcf5382e74e6ce05839b33 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:15 +0100
Subject: lmb: fix allocation at end of address range
The lmb code fails if base + size of RAM overflows to zero.
Fix this by calculating end as 'base + size - 1' instead of 'base + size'
where appropriate.
Added tests to assert this is fixed.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
diff --git a/lib/lmb.c b/lib/lmb.c
index 17054173..6d3dcf4e 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -43,7 +43,10 @@ void lmb_dump_all(struct lmb *lmb)
static long lmb_addrs_overlap(phys_addr_t base1,
phys_size_t size1, phys_addr_t base2, phys_size_t size2)
{
- return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+ const phys_addr_t base1_end = base1 + size1 - 1;
+ const phys_addr_t base2_end = base2 + size2 - 1;
+
+ return ((base1 <= base2_end) && (base2 <= base1_end));
}
static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1,
@@ -89,18 +92,9 @@ static void lmb_coalesce_regions(struct lmb_region *rgn,
void lmb_init(struct lmb *lmb)
{
- /* Create a dummy zero size LMB which will get coalesced away later.
- * This simplifies the lmb_add() code below...
- */
- lmb->memory.region[0].base = 0;
- lmb->memory.region[0].size = 0;
- lmb->memory.cnt = 1;
+ lmb->memory.cnt = 0;
lmb->memory.size = 0;
-
- /* Ditto. */
- lmb->reserved.region[0].base = 0;
- lmb->reserved.region[0].size = 0;
- lmb->reserved.cnt = 1;
+ lmb->reserved.cnt = 0;
lmb->reserved.size = 0;
}
@@ -110,9 +104,10 @@ static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t
unsigned long coalesced = 0;
long adjacent, i;
- if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
+ if (rgn->cnt == 0) {
rgn->region[0].base = base;
rgn->region[0].size = size;
+ rgn->cnt = 1;
return 0;
}
@@ -183,7 +178,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size)
{
struct lmb_region *rgn = &(lmb->reserved);
phys_addr_t rgnbegin, rgnend;
- phys_addr_t end = base + size;
+ phys_addr_t end = base + size - 1;
int i;
rgnbegin = rgnend = 0; /* supress gcc warnings */
@@ -191,7 +186,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size)
/* Find the region where (base, size) belongs to */
for (i=0; i < rgn->cnt; i++) {
rgnbegin = rgn->region[i].base;
- rgnend = rgnbegin + rgn->region[i].size;
+ rgnend = rgnbegin + rgn->region[i].size - 1;
if ((rgnbegin <= base) && (end <= rgnend))
break;
@@ -209,7 +204,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size)
/* Check to see if region is matching at the front */
if (rgnbegin == base) {
- rgn->region[i].base = end;
+ rgn->region[i].base = end + 1;
rgn->region[i].size -= size;
return 0;
}
@@ -225,7 +220,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size)
* beginging of the hole and add the region after hole.
*/
rgn->region[i].size = base - rgn->region[i].base;
- return lmb_add_region(rgn, end, rgnend - end);
+ return lmb_add_region(rgn, end + 1, rgnend - end);
}
long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size)
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index dd7ba14b..fb7ca45e 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -146,8 +146,15 @@ static int test_multi_alloc_512mb(struct unit_test_state *uts,
/* Create a memory region with one reserved region and allocate */
static int lib_test_lmb_simple(struct unit_test_state *uts)
{
+ int ret;
+
/* simulate 512 MiB RAM beginning at 1GiB */
- return test_multi_alloc_512mb(uts, 0x40000000);
+ ret = test_multi_alloc_512mb(uts, 0x40000000);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_multi_alloc_512mb(uts, 0xE0000000);
}
DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
@@ -206,7 +213,15 @@ static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
static int lib_test_lmb_big(struct unit_test_state *uts)
{
- return test_bigblock(uts, 0x40000000);
+ int ret;
+
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ ret = test_bigblock(uts, 0x40000000);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_bigblock(uts, 0xE0000000);
}
DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
@@ -247,7 +262,15 @@ static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram)
static int lib_test_lmb_noreserved(struct unit_test_state *uts)
{
- return test_noreserved(uts, 0x40000000);
+ int ret;
+
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ ret = test_noreserved(uts, 0x40000000);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_noreserved(uts, 0xE0000000);
}
DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
1.8.3.1

View file

@ -1,208 +0,0 @@
From 0b66765ffcdc995177753b7e6607be477593041e Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:16 +0100
Subject: lib: lmb: reserving overlapping regions should fail
lmb_add_region handles overlapping regions wrong: instead of merging
or rejecting to add a new reserved region that overlaps an existing
one, it just adds the new region.
Since internally the same function is used for lmb_alloc, change
lmb_add_region to reject overlapping regions.
Also, to keep reserved memory correct after 'free', reserved entries
created by allocating memory must not set their size to a multiple
of alignment but to the original size. This ensures the reserved
region is completely removed when the caller calls 'lmb_free', as
this one takes the same size as passed to 'lmb_alloc' etc.
Add test to assert this.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
diff --git a/lib/lmb.c b/lib/lmb.c
index 6d3dcf4e..cd297f82 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -131,6 +131,9 @@ static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t
rgn->region[i].size += size;
coalesced++;
break;
+ } else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) {
+ /* regions overlap */
+ return -1;
}
}
@@ -269,11 +272,6 @@ static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size)
return addr & ~(size - 1);
}
-static phys_addr_t lmb_align_up(phys_addr_t addr, ulong size)
-{
- return (addr + (size - 1)) & ~(size - 1);
-}
-
phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr)
{
long i, j;
@@ -302,8 +300,7 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy
if (j < 0) {
/* This area isn't reserved, take it */
if (lmb_add_region(&lmb->reserved, base,
- lmb_align_up(size,
- align)) < 0)
+ size) < 0)
return 0;
return base;
}
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index fb7ca45e..e6acb70e 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -227,13 +227,16 @@ static int lib_test_lmb_big(struct unit_test_state *uts)
DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Simulate 512 MiB RAM, allocate a block without previous reservation */
-static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram)
+static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
+ const phys_addr_t alloc_size, const ulong align)
{
const phys_size_t ram_size = 0x20000000;
const phys_addr_t ram_end = ram + ram_size;
struct lmb lmb;
long ret;
phys_addr_t a, b;
+ const phys_addr_t alloc_size_aligned = (alloc_size + align - 1) &
+ ~(align - 1);
/* check for overflow */
ut_assert(ram_end == 0 || ram_end > ram);
@@ -242,20 +245,43 @@ static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram)
ret = lmb_add(&lmb, ram, ram_size);
ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
/* allocate a block */
- a = lmb_alloc(&lmb, 4, 1);
+ a = lmb_alloc(&lmb, alloc_size, align);
ut_assert(a != 0);
- /* and free it */
- ret = lmb_free(&lmb, a, 4);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+ alloc_size, 0, 0, 0, 0);
+ /* allocate another block */
+ b = lmb_alloc(&lmb, alloc_size, align);
+ ut_assert(b != 0);
+ if (alloc_size == alloc_size_aligned) {
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size -
+ (alloc_size_aligned * 2), alloc_size * 2, 0, 0, 0,
+ 0);
+ } else {
+ ASSERT_LMB(&lmb, ram, ram_size, 2, ram + ram_size -
+ (alloc_size_aligned * 2), alloc_size, ram + ram_size
+ - alloc_size_aligned, alloc_size, 0, 0);
+ }
+ /* and free them */
+ ret = lmb_free(&lmb, b, alloc_size);
ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+ alloc_size, 0, 0, 0, 0);
+ ret = lmb_free(&lmb, a, alloc_size);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
/* allocate a block with base*/
- b = lmb_alloc_base(&lmb, 4, 1, ram_end);
+ b = lmb_alloc_base(&lmb, alloc_size, align, ram_end);
ut_assert(a == b);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned,
+ alloc_size, 0, 0, 0, 0);
/* and free it */
- ret = lmb_free(&lmb, b, 4);
+ ret = lmb_free(&lmb, b, alloc_size);
ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0);
return 0;
}
@@ -265,16 +291,30 @@ static int lib_test_lmb_noreserved(struct unit_test_state *uts)
int ret;
/* simulate 512 MiB RAM beginning at 1GiB */
- ret = test_noreserved(uts, 0x40000000);
+ ret = test_noreserved(uts, 0x40000000, 4, 1);
if (ret)
return ret;
/* simulate 512 MiB RAM beginning at 1.5GiB */
- return test_noreserved(uts, 0xE0000000);
+ return test_noreserved(uts, 0xE0000000, 4, 1);
}
DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
+{
+ int ret;
+
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ ret = test_noreserved(uts, 0x40000000, 5, 8);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_noreserved(uts, 0xE0000000, 5, 8);
+}
+
+DM_TEST(lib_test_lmb_unaligned_size, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/*
* Simulate a RAM that starts at 0 and allocate down to address 0, which must
* fail as '0' means failure for the lmb_alloc functions.
@@ -318,3 +358,42 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
}
DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Check that calling lmb_reserve with overlapping regions fails. */
+static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
+{
+ const phys_addr_t ram = 0x40000000;
+ const phys_size_t ram_size = 0x20000000;
+ struct lmb lmb;
+ long ret;
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ ret = lmb_reserve(&lmb, 0x40010000, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
+ 0, 0, 0, 0);
+ /* allocate overlapping region should fail */
+ ret = lmb_reserve(&lmb, 0x40011000, 0x10000);
+ ut_asserteq(ret, -1);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
+ 0, 0, 0, 0);
+ /* allocate 3nd region */
+ ret = lmb_reserve(&lmb, 0x40030000, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40010000, 0x10000,
+ 0x40030000, 0x10000, 0, 0);
+ /* allocate 2nd region */
+ ret = lmb_reserve(&lmb, 0x40020000, 0x10000);
+ ut_assert(ret >= 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000,
+ 0, 0, 0, 0);
+
+ return 0;
+}
+
+DM_TEST(lib_test_lmb_overlapping_reserve,
+ DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
1.8.3.1

View file

@ -1,117 +0,0 @@
From 83dc6df2cff9e91e77890107c74d4858182e4b61 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:17 +0100
Subject: fdt: parse "reserved-memory" for memory reservation
boot_fdt_add_mem_rsv_regions() adds reserved memory sections to an lmb
struct. Currently, it only parses regions described by /memreserve/
entries.
Extend this to the more commonly used scheme of the "reserved-memory"
node.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 95748f0a..5c0d6db3 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <fdt_support.h>
+#include <fdtdec.h>
#include <errno.h>
#include <image.h>
#include <linux/libfdt.h>
@@ -67,30 +68,66 @@ static const image_header_t *image_get_fdt(ulong fdt_addr)
}
#endif
+static void boot_fdt_reserve_region(struct lmb *lmb, uint64_t addr,
+ uint64_t size)
+{
+ int ret;
+
+ ret = lmb_reserve(lmb, addr, size);
+ if (!ret) {
+ debug(" reserving fdt memory region: addr=%llx size=%llx\n",
+ (unsigned long long)addr, (unsigned long long)size);
+ } else {
+ puts("ERROR: reserving fdt memory region failed ");
+ printf("(addr=%llx size=%llx)\n",
+ (unsigned long long)addr, (unsigned long long)size);
+ }
+}
+
/**
- * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
+ * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory
+ * sections as unusable
* @lmb: pointer to lmb handle, will be used for memory mgmt
* @fdt_blob: pointer to fdt blob base address
*
- * Adds the memreserve regions in the dtb to the lmb block. Adding the
- * memreserve regions prevents u-boot from using them to store the initrd
- * or the fdt blob.
+ * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block.
+ * Adding the memreserve regions prevents u-boot from using them to store the
+ * initrd or the fdt blob.
*/
void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
{
uint64_t addr, size;
- int i, total;
+ int i, total, ret;
+ int nodeoffset, subnode;
+ struct fdt_resource res;
if (fdt_check_header(fdt_blob) != 0)
return;
+ /* process memreserve sections */
total = fdt_num_mem_rsv(fdt_blob);
for (i = 0; i < total; i++) {
if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
continue;
- printf(" reserving fdt memory region: addr=%llx size=%llx\n",
- (unsigned long long)addr, (unsigned long long)size);
- lmb_reserve(lmb, addr, size);
+ boot_fdt_reserve_region(lmb, addr, size);
+ }
+
+ /* process reserved-memory */
+ nodeoffset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory");
+ if (nodeoffset >= 0) {
+ subnode = fdt_first_subnode(fdt_blob, nodeoffset);
+ while (subnode >= 0) {
+ /* check if this subnode has a reg property */
+ ret = fdt_get_resource(fdt_blob, subnode, "reg", 0,
+ &res);
+ if (!ret) {
+ addr = res.start;
+ size = res.end - res.start + 1;
+ boot_fdt_reserve_region(lmb, addr, size);
+ }
+
+ subnode = fdt_next_subnode(fdt_blob, subnode);
+ }
}
}
diff --git a/lib/Makefile b/lib/Makefile
index a6dd928a..358789ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -30,6 +30,7 @@ obj-y += crc7.o
obj-y += crc8.o
obj-y += crc16.o
obj-$(CONFIG_ERRNO_STR) += errno_str.o
+obj-$(CONFIG_OF_LIBFDT) += fdtdec.o
obj-$(CONFIG_FIT) += fdtdec_common.o
obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
--
1.8.3.1

View file

@ -1,312 +0,0 @@
From 16448a9becefd10a64601a08bbcacea38075db70 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:18 +0100
Subject: lib: lmb: extend lmb for checks at load time
This adds two new functions, lmb_alloc_addr and
lmb_get_unreserved_size.
lmb_alloc_addr behaves like lmb_alloc, but it tries to allocate a
pre-specified address range. Unlike lmb_reserve, this address range
must be inside one of the memory ranges that has been set up with
lmb_add.
lmb_get_unreserved_size returns the number of bytes that can be
used up to the next reserved region or the end of valid ram. This
can be 0 if the address passed is reserved.
Added test for these new functions.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
diff --git a/include/lmb.h b/include/lmb.h
index f04d0580..7d7e2a78 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -38,6 +38,9 @@ extern phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align
phys_addr_t max_addr);
extern phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
phys_addr_t max_addr);
+extern phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base,
+ phys_size_t size);
+extern phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr);
extern int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
extern long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size);
diff --git a/lib/lmb.c b/lib/lmb.c
index cd297f82..e380a0a7 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -313,6 +313,59 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy
return 0;
}
+/*
+ * Try to allocate a specific address range: must be in defined memory but not
+ * reserved
+ */
+phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+{
+ long j;
+
+ /* Check if the requested address is in one of the memory regions */
+ j = lmb_overlaps_region(&lmb->memory, base, size);
+ if (j >= 0) {
+ /*
+ * Check if the requested end address is in the same memory
+ * region we found.
+ */
+ if (lmb_addrs_overlap(lmb->memory.region[j].base,
+ lmb->memory.region[j].size, base + size -
+ 1, 1)) {
+ /* ok, reserve the memory */
+ if (lmb_reserve(lmb, base, size) >= 0)
+ return base;
+ }
+ }
+ return 0;
+}
+
+/* Return number of bytes from a given address that are free */
+phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr)
+{
+ int i;
+ long j;
+
+ /* check if the requested address is in the memory regions */
+ j = lmb_overlaps_region(&lmb->memory, addr, 1);
+ if (j >= 0) {
+ for (i = 0; i < lmb->reserved.cnt; i++) {
+ if (addr < lmb->reserved.region[i].base) {
+ /* first reserved range > requested address */
+ return lmb->reserved.region[i].base - addr;
+ }
+ if (lmb->reserved.region[i].base +
+ lmb->reserved.region[i].size > addr) {
+ /* requested addr is in this reserved range */
+ return 0;
+ }
+ }
+ /* if we come here: no reserved ranges above requested addr */
+ return lmb->memory.region[lmb->memory.cnt - 1].base +
+ lmb->memory.region[lmb->memory.cnt - 1].size - addr;
+ }
+ return 0;
+}
+
int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr)
{
int i;
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index e6acb70e..058d3c33 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -397,3 +397,205 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
DM_TEST(lib_test_lmb_overlapping_reserve,
DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/*
+ * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between.
+ * Expect addresses outside the memory range to fail.
+ */
+static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
+{
+ const phys_size_t ram_size = 0x20000000;
+ const phys_addr_t ram_end = ram + ram_size;
+ const phys_size_t alloc_addr_a = ram + 0x8000000;
+ const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
+ const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
+ struct lmb lmb;
+ long ret;
+ phys_addr_t a, b, c, d, e;
+
+ /* check for overflow */
+ ut_assert(ram_end == 0 || ram_end > ram);
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* reserve 3 blocks */
+ ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
+ ut_asserteq(ret, 0);
+ ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
+ ut_asserteq(ret, 0);
+ ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
+ alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+
+ /* allocate blocks */
+ a = lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram);
+ ut_asserteq(a, ram);
+ ASSERT_LMB(&lmb, ram, ram_size, 3, ram, 0x8010000,
+ alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+ b = lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000,
+ alloc_addr_b - alloc_addr_a - 0x10000);
+ ut_asserteq(b, alloc_addr_a + 0x10000);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x10010000,
+ alloc_addr_c, 0x10000, 0, 0);
+ c = lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000,
+ alloc_addr_c - alloc_addr_b - 0x10000);
+ ut_asserteq(c, alloc_addr_b + 0x10000);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+ 0, 0, 0, 0);
+ d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000,
+ ram_end - alloc_addr_c - 0x10000);
+ ut_asserteq(d, alloc_addr_c + 0x10000);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
+ 0, 0, 0, 0);
+
+ /* allocating anything else should fail */
+ e = lmb_alloc(&lmb, 1, 1);
+ ut_asserteq(e, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
+ 0, 0, 0, 0);
+
+ ret = lmb_free(&lmb, d, ram_end - alloc_addr_c - 0x10000);
+ ut_asserteq(ret, 0);
+
+ /* allocate at 3 points in free range */
+
+ d = lmb_alloc_addr(&lmb, ram_end - 4, 4);
+ ut_asserteq(d, ram_end - 4);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
+ d, 4, 0, 0);
+ ret = lmb_free(&lmb, d, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+ 0, 0, 0, 0);
+
+ d = lmb_alloc_addr(&lmb, ram_end - 128, 4);
+ ut_asserteq(d, ram_end - 128);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
+ d, 4, 0, 0);
+ ret = lmb_free(&lmb, d, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+ 0, 0, 0, 0);
+
+ d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4);
+ ut_asserteq(d, alloc_addr_c + 0x10000);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010004,
+ 0, 0, 0, 0);
+ ret = lmb_free(&lmb, d, 4);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
+ 0, 0, 0, 0);
+
+ /* allocate at the bottom */
+ ret = lmb_free(&lmb, a, alloc_addr_a - ram);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, ram + 0x8000000, 0x10010000,
+ 0, 0, 0, 0);
+ d = lmb_alloc_addr(&lmb, ram, 4);
+ ut_asserteq(d, ram);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, d, 4,
+ ram + 0x8000000, 0x10010000, 0, 0);
+
+ /* check that allocating outside memory fails */
+ if (ram_end != 0) {
+ ret = lmb_alloc_addr(&lmb, ram_end, 1);
+ ut_asserteq(ret, 0);
+ }
+ if (ram != 0) {
+ ret = lmb_alloc_addr(&lmb, ram - 1, 1);
+ ut_asserteq(ret, 0);
+ }
+
+ return 0;
+}
+
+static int lib_test_lmb_alloc_addr(struct unit_test_state *uts)
+{
+ int ret;
+
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ ret = test_alloc_addr(uts, 0x40000000);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_alloc_addr(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_alloc_addr, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */
+static int test_get_unreserved_size(struct unit_test_state *uts,
+ const phys_addr_t ram)
+{
+ const phys_size_t ram_size = 0x20000000;
+ const phys_addr_t ram_end = ram + ram_size;
+ const phys_size_t alloc_addr_a = ram + 0x8000000;
+ const phys_size_t alloc_addr_b = ram + 0x8000000 * 2;
+ const phys_size_t alloc_addr_c = ram + 0x8000000 * 3;
+ struct lmb lmb;
+ long ret;
+ phys_size_t s;
+
+ /* check for overflow */
+ ut_assert(ram_end == 0 || ram_end > ram);
+
+ lmb_init(&lmb);
+
+ ret = lmb_add(&lmb, ram, ram_size);
+ ut_asserteq(ret, 0);
+
+ /* reserve 3 blocks */
+ ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000);
+ ut_asserteq(ret, 0);
+ ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000);
+ ut_asserteq(ret, 0);
+ ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000);
+ ut_asserteq(ret, 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000,
+ alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
+
+ /* check addresses in between blocks */
+ s = lmb_get_unreserved_size(&lmb, ram);
+ ut_asserteq(s, alloc_addr_a - ram);
+ s = lmb_get_unreserved_size(&lmb, ram + 0x10000);
+ ut_asserteq(s, alloc_addr_a - ram - 0x10000);
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_a - 4);
+ ut_asserteq(s, 4);
+
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x10000);
+ ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x10000);
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x20000);
+ ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x20000);
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_b - 4);
+ ut_asserteq(s, 4);
+
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x10000);
+ ut_asserteq(s, ram_end - alloc_addr_c - 0x10000);
+ s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x20000);
+ ut_asserteq(s, ram_end - alloc_addr_c - 0x20000);
+ s = lmb_get_unreserved_size(&lmb, ram_end - 4);
+ ut_asserteq(s, 4);
+
+ return 0;
+}
+
+static int lib_test_lmb_get_unreserved_size(struct unit_test_state *uts)
+{
+ int ret;
+
+ /* simulate 512 MiB RAM beginning at 1GiB */
+ ret = test_get_unreserved_size(uts, 0x40000000);
+ if (ret)
+ return ret;
+
+ /* simulate 512 MiB RAM beginning at 1.5GiB */
+ return test_get_unreserved_size(uts, 0xE0000000);
+}
+
+DM_TEST(lib_test_lmb_get_unreserved_size,
+ DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
1.8.3.1

View file

@ -1,138 +0,0 @@
From 94e5a755db2a72b8bdaceb634b732ed59816b5ac Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:19 +0100
Subject: fs: prevent overwriting reserved memory
This fixes CVE-2018-18440 ("insufficient boundary checks in filesystem
image load") by using lmb to check the load size of a file against
reserved memory addresses.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/fs/fs.c b/fs/fs.c
index cb265174..7fd22101 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -429,13 +429,57 @@ int fs_size(const char *filename, loff_t *size)
return ret;
}
-int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
- loff_t *actread)
+#ifdef CONFIG_LMB
+/* Check if a file may be read to the given address */
+static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
+ loff_t len, struct fstype_info *info)
+{
+ struct lmb lmb;
+ int ret;
+ loff_t size;
+ loff_t read_len;
+
+ /* get the actual size of the file */
+ ret = info->size(filename, &size);
+ if (ret)
+ return ret;
+ if (offset >= size) {
+ /* offset >= EOF, no bytes will be written */
+ return 0;
+ }
+ read_len = size - offset;
+
+ /* limit to 'len' if it is smaller */
+ if (len && len < read_len)
+ read_len = len;
+
+ lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start,
+ gd->bd->bi_dram[0].size, (void *)gd->fdt_blob);
+ lmb_dump_all(&lmb);
+
+ if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
+ return 0;
+
+ printf("** Reading file would overwrite reserved memory **\n");
+ return -ENOSPC;
+}
+#endif
+
+static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
+ int do_lmb_check, loff_t *actread)
{
struct fstype_info *info = fs_get_info(fs_type);
void *buf;
int ret;
+#ifdef CONFIG_LMB
+ if (do_lmb_check) {
+ ret = fs_read_lmb_check(filename, addr, offset, len, info);
+ if (ret)
+ return ret;
+ }
+#endif
+
/*
* We don't actually know how many bytes are being read, since len==0
* means read the whole file.
@@ -452,6 +496,12 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
return ret;
}
+int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
+ loff_t *actread)
+{
+ return _fs_read(filename, addr, offset, len, 0, actread);
+}
+
int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
loff_t *actwrite)
{
@@ -622,7 +672,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
pos = 0;
time = get_timer(0);
- ret = fs_read(filename, addr, pos, bytes, &len_read);
+ ret = _fs_read(filename, addr, pos, bytes, 1, &len_read);
time = get_timer(time);
if (ret < 0)
return 1;
diff --git a/include/lmb.h b/include/lmb.h
index 7d7e2a78..62da85e7 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -31,6 +31,8 @@ struct lmb {
extern struct lmb lmb;
extern void lmb_init(struct lmb *lmb);
+extern void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base,
+ phys_size_t size, void *fdt_blob);
extern long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size);
extern long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size);
extern phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
diff --git a/lib/lmb.c b/lib/lmb.c
index e380a0a7..3407705f 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -98,6 +98,19 @@ void lmb_init(struct lmb *lmb)
lmb->reserved.size = 0;
}
+/* Initialize the struct, add memory and call arch/board reserve functions */
+void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size,
+ void *fdt_blob)
+{
+ lmb_init(lmb);
+ lmb_add(lmb, base, size);
+ arch_lmb_reserve(lmb);
+ board_lmb_reserve(lmb);
+
+ if (IMAGE_ENABLE_OF_LIBFDT && fdt_blob)
+ boot_fdt_add_mem_rsv_regions(lmb, fdt_blob);
+}
+
/* This routine called with relocation disabled. */
static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t size)
{
--
1.8.3.1

View file

@ -1,35 +0,0 @@
From 2e3bdfbc449a5558ebbb55e36feee31f69fe32f7 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:20 +0100
Subject: bootm: use new common function lmb_init_and_reserve
This reduces duplicate code only.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/common/bootm.c b/common/bootm.c
index 8bf84ebc..31e4f0f7 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -56,15 +56,11 @@ static void boot_start_lmb(bootm_headers_t *images)
ulong mem_start;
phys_size_t mem_size;
- lmb_init(&images->lmb);
-
mem_start = env_get_bootm_low();
mem_size = env_get_bootm_size();
- lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
-
- arch_lmb_reserve(&images->lmb);
- board_lmb_reserve(&images->lmb);
+ lmb_init_and_reserve(&images->lmb, (phys_addr_t)mem_start, mem_size,
+ NULL);
}
#else
#define lmb_reserve(lmb, base, size)
--
1.8.3.1

View file

@ -1,26 +0,0 @@
From 8b554b62dcab25c0072c5b6880d0fcf079cc9d87 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:21 +0100
Subject: lmb: remove unused extern declaration
lmb.h includes an extern declaration of "struct lmb lmb;" which
is not used anywhere, so remove it.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
diff --git a/include/lmb.h b/include/lmb.h
index 62da85e7..1bb003e3 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -28,8 +28,6 @@ struct lmb {
struct lmb_region reserved;
};
-extern struct lmb lmb;
-
extern void lmb_init(struct lmb *lmb);
extern void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base,
phys_size_t size, void *fdt_blob);
--
1.8.3.1

View file

@ -1,172 +0,0 @@
From 2e972e30c0b07736fedcc4fad53cfe49249495a5 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:22 +0100
Subject: tftp: prevent overwriting reserved memory
This fixes CVE-2018-18439 ("insufficient boundary checks in network
image boot") by using lmb to check for a valid range to store
received blocks.
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
diff --git a/net/tftp.c b/net/tftp.c
index 68ffd814..a9335b1b 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -17,6 +17,8 @@
#include <flash.h>
#endif
+DECLARE_GLOBAL_DATA_PTR;
+
/* Well known TFTP port # */
#define WELL_KNOWN_PORT 69
/* Millisecs to timeout for lost pkt */
@@ -81,6 +83,10 @@ static ulong tftp_block_wrap;
/* memory offset due to wrapping */
static ulong tftp_block_wrap_offset;
static int tftp_state;
+static ulong tftp_load_addr;
+#ifdef CONFIG_LMB
+static ulong tftp_load_size;
+#endif
#ifdef CONFIG_TFTP_TSIZE
/* The file size reported by the server */
static int tftp_tsize;
@@ -164,10 +170,11 @@ static void mcast_cleanup(void)
#endif /* CONFIG_MCAST_TFTP */
-static inline void store_block(int block, uchar *src, unsigned len)
+static inline int store_block(int block, uchar *src, unsigned int len)
{
ulong offset = block * tftp_block_size + tftp_block_wrap_offset;
ulong newsize = offset + len;
+ ulong store_addr = tftp_load_addr + offset;
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
int i, rc = 0;
@@ -175,24 +182,32 @@ static inline void store_block(int block, uchar *src, unsigned len)
/* start address in flash? */
if (flash_info[i].flash_id == FLASH_UNKNOWN)
continue;
- if (load_addr + offset >= flash_info[i].start[0]) {
+ if (store_addr >= flash_info[i].start[0]) {
rc = 1;
break;
}
}
if (rc) { /* Flash is destination for this packet */
- rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
+ rc = flash_write((char *)src, store_addr, len);
if (rc) {
flash_perror(rc);
- net_set_state(NETLOOP_FAIL);
- return;
+ return rc;
}
} else
#endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
{
- void *ptr = map_sysmem(load_addr + offset, len);
-
+ void *ptr;
+
+#ifdef CONFIG_LMB
+ if (store_addr < tftp_load_addr ||
+ store_addr + len > tftp_load_addr + tftp_load_size) {
+ puts("\nTFTP error: ");
+ puts("trying to overwrite reserved memory...\n");
+ return -1;
+ }
+#endif
+ ptr = map_sysmem(store_addr, len);
memcpy(ptr, src, len);
unmap_sysmem(ptr);
}
@@ -203,6 +218,8 @@ static inline void store_block(int block, uchar *src, unsigned len)
if (net_boot_file_size < newsize)
net_boot_file_size = newsize;
+
+ return 0;
}
/* Clear our state ready for a new transfer */
@@ -606,7 +623,11 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
timeout_count_max = tftp_timeout_count_max;
net_set_timeout_handler(timeout_ms, tftp_timeout_handler);
- store_block(tftp_cur_block - 1, pkt + 2, len);
+ if (store_block(tftp_cur_block - 1, pkt + 2, len)) {
+ eth_halt();
+ net_set_state(NETLOOP_FAIL);
+ break;
+ }
/*
* Acknowledge the block just received, which will prompt
@@ -695,6 +716,25 @@ static void tftp_timeout_handler(void)
}
}
+/* Initialize tftp_load_addr and tftp_load_size from load_addr and lmb */
+static int tftp_init_load_addr(void)
+{
+#ifdef CONFIG_LMB
+ struct lmb lmb;
+ phys_size_t max_size;
+
+ lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start,
+ gd->bd->bi_dram[0].size, (void *)gd->fdt_blob);
+
+ max_size = lmb_get_unreserved_size(&lmb, load_addr);
+ if (!max_size)
+ return -1;
+
+ tftp_load_size = max_size;
+#endif
+ tftp_load_addr = load_addr;
+ return 0;
+}
void tftp_start(enum proto_t protocol)
{
@@ -791,7 +831,14 @@ void tftp_start(enum proto_t protocol)
} else
#endif
{
- printf("Load address: 0x%lx\n", load_addr);
+ if (tftp_init_load_addr()) {
+ eth_halt();
+ net_set_state(NETLOOP_FAIL);
+ puts("\nTFTP error: ");
+ puts("trying to overwrite reserved memory...\n");
+ return;
+ }
+ printf("Load address: 0x%lx\n", tftp_load_addr);
puts("Loading: *\b");
tftp_state = STATE_SEND_RRQ;
#ifdef CONFIG_CMD_BOOTEFI
@@ -842,9 +889,15 @@ void tftp_start_server(void)
{
tftp_filename[0] = 0;
+ if (tftp_init_load_addr()) {
+ eth_halt();
+ net_set_state(NETLOOP_FAIL);
+ puts("\nTFTP error: trying to overwrite reserved memory...\n");
+ return;
+ }
printf("Using %s device\n", eth_get_name());
printf("Listening for TFTP transfer on %pI4\n", &net_ip);
- printf("Load address: 0x%lx\n", load_addr);
+ printf("Load address: 0x%lx\n", tftp_load_addr);
puts("Loading: *\b");
--
1.8.3.1

View file

@ -1,46 +0,0 @@
From 72bc6aa0bc7f034bd6966c872819f19af69f2b64 Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Date: Mon, 14 Jan 2019 22:38:23 +0100
Subject: arm: bootm: fix sp detection at end of address range
This fixes 'arch_lmb_reserve()' for ARM that tries to detect in which
DRAM bank 'sp' is in.
This code failed if a bank was at the end of physical address range
(i.e. size + length overflowed to 0).
To fix this, calculate 'bank_end' as 'size + length - 1' so that such
banks end at 0xffffffff, not 0.
Fixes: 15751403b6 ("ARM: bootm: don't assume sp is in DRAM bank 0")
Reported-by: Frank Wunderlich <frank-w@public-files.de>
Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index c3c1d2fd..329f20c2 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -64,13 +64,15 @@ void arch_lmb_reserve(struct lmb *lmb)
/* adjust sp by 4K to be safe */
sp -= 4096;
for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
- if (sp < gd->bd->bi_dram[bank].start)
+ if (!gd->bd->bi_dram[bank].size ||
+ sp < gd->bd->bi_dram[bank].start)
continue;
+ /* Watch out for RAM at end of address space! */
bank_end = gd->bd->bi_dram[bank].start +
- gd->bd->bi_dram[bank].size;
- if (sp >= bank_end)
+ gd->bd->bi_dram[bank].size - 1;
+ if (sp > bank_end)
continue;
- lmb_reserve(lmb, sp, bank_end - sp);
+ lmb_reserve(lmb, sp, bank_end - sp + 1);
break;
}
}
--
1.8.3.1

View file

@ -1,27 +0,0 @@
From 7b492a978a09fbc95340dbcdc1e14d604ac6ae76 Mon Sep 17 00:00:00 2001
From: Frank Wunderlich <frank-w@public-files.de>
Date: Wed, 23 Jan 2019 16:16:45 +0100
Subject: [defconfig] added strings and setenv used for lstftp
diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig
index a9f4506e..bac45d11 100644
--- a/configs/mt7623n_bpir2_defconfig
+++ b/configs/mt7623n_bpir2_defconfig
@@ -22,7 +22,6 @@ CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PART=y
CONFIG_CMD_READ=y
-# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
CONFIG_CMD_PING=y
CONFIG_CMD_FAT=y
@@ -69,3 +68,5 @@ CONFIG_DEFAULT_ENV_FILE="uEnv.txt"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_CMD_ASKENV=y
+CONFIG_CMD_STRINGS=y
+CONFIG_CMD_SETEXPR=y
--
1.8.3.1

View file

@ -1,22 +0,0 @@
From 0164e641d4a64dcff5d5394b168d612b174d83bd Mon Sep 17 00:00:00 2001
From: Frank Wunderlich <frank-w@public-files.de>
Date: Wed, 23 Jan 2019 16:30:39 +0100
Subject: increase size for environment 4k => 8k
diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h
index 7d26debb..aa0314db 100644
--- a/include/configs/mt7623.h
+++ b/include/configs/mt7623.h
@@ -27,7 +27,7 @@
#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M
/* Environment */
-#define CONFIG_ENV_SIZE SZ_4K
+#define CONFIG_ENV_SIZE SZ_8K
/* Allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
--
1.8.3.1

View file

@ -4,9 +4,9 @@ bootenv=uEnv.txt
kernel=uImage
loadaddr=0x80200000
#default bootargs will be overidden by buildargs
bootargs=console=ttyS0,115200 root=/dev/mmcblk1p2 rw rootwait ip=dhcp
bootargs=console=ttyS2,115200 root=/dev/mmcblk1p2 rw rootwait ip=dhcp
console=earlyprintk console=ttyS0,115200 console=tty1 fbcon=map:0
console=earlyprintk console=ttyS2,115200 console=tty1 fbcon=map:0
roottmpl=${rootdev} rootfstype=ext4 rootwait
prepsetroot=setenv setroot setenv root ${roottmpl}
bootopts=vmalloc=496M debug=7 initcall_debug=0
@ -65,7 +65,7 @@ netmask=255.255.255.0
serverip=192.168.0.10
bootfile=uImage
netbootargs=console=ttyS0,115200 root=/dev/mmcblk1p2 rw rootwait
netbootargs=console=ttyS2,115200 root=/dev/mmcblk1p2 rw rootwait
#ip=dhcp sets ip on eth0 instead of wan
lstftp=tftp ${loadaddr} ${serverip}:files.lst;setexpr listend ${loadaddr} + ${filesize};mw.b ${listend} 00 2;strings ${loadaddr};