Initial commit

This commit is contained in:
domenico
2025-06-24 13:14:22 +02:00
commit 4002f145fc
9002 changed files with 1731834 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
# SPDX-License-Identifier: GPL-2.0-or-later
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
KERNEL_LOADADDR := 0x80010000 # RAM start + 64K
LOADER_ENTRY := 0x80a00000 # RAM start + 10M, for relocate
RAMSIZE := 0x02000000 # 32MB
LZMA_TEXT_START := 0x81800000 # 32MB - 8MB
DEVICE_VARS += CHIP_ID DEVICE_LOADADDR
define Build/Compile
rm -rf $(KDIR)/relocate
$(CP) ../../generic/image/relocate $(KDIR)
$(MAKE) -C $(KDIR)/relocate \
CACHELINE_SIZE=16 \
CROSS_COMPILE=$(TARGET_CROSS) \
KERNEL_ADDR=$(KERNEL_LOADADDR) \
LZMA_TEXT_START=$(LOADER_ENTRY)
endef
### Kernel scripts ###
define Build/loader-lzma
@rm -rf $@.src
$(MAKE) -C lzma-loader \
CHIP_ID=$(CHIP_ID) \
KERNEL_ADDR=$(KERNEL_LOADADDR) \
KDIR=$(KDIR) \
LOADER_ADDR=$(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \
LOADER_DATA="$@" \
LOADER_NAME="$(notdir $@)" \
LZMA_TEXT_START=$(LZMA_TEXT_START) \
PKG_BUILD_DIR="$@.src" \
RAMSIZE=$(RAMSIZE) \
TARGET_DIR="$(dir $@)" \
compile loader.$(1)
@mv "$@.$(1)" "$@"
@rm -rf $@.src
endef
define Build/lzma-cfe
# CFE is a LZMA nazi! It took me hours to find out the parameters!
# Also I think lzma has a bug cause it generates different output depending on
# if you use stdin / stdout or not. Use files instead of stdio here, cause
# otherwise CFE will complain and not boot the image.
$(call Build/lzma-no-dict,-d22 -fb64 -a1)
# Strip out the length, CFE doesn't like this
dd if=$@ of=$@.new bs=5 count=1
dd if=$@ of=$@.new ibs=13 obs=5 skip=1 seek=1 conv=notrunc
@mv $@.new $@
endef
define Build/relocate-kernel
# CFE only allows ~4 MiB for the uncompressed kernels, but uncompressed
# kernel might get larger than that, so let CFE unpack and load at a
# higher address and make the kernel relocate itself to the expected
# location.
( \
dd if=$(KDIR)/relocate/loader.bin bs=32 conv=sync && \
perl -e '@s = stat("$@"); print pack("N", @s[7])' && \
cat $@ \
) > $@.relocate
@mv $@.relocate $@
endef
### Image scripts ###
define rootfspad/jffs2-128k
--align-rootfs
endef
define rootfspad/jffs2-64k
--align-rootfs
endef
define rootfspad/squashfs
endef
define Image/FileSystemStrip
$(firstword $(subst +,$(space),$(subst root.,,$(notdir $(1)))))
endef
define Build/cfe-bin
$(STAGING_DIR_HOST)/bin/imagetag -i $(IMAGE_KERNEL) -f $(IMAGE_ROOTFS) \
--output $@ --boardid $(CFE_BOARD_ID) --chipid $(CHIP_ID) \
--entry $(LOADER_ENTRY) --load-addr $(LOADER_ENTRY) \
--info1 "$(call ModelNameLimit16,$(DEVICE_NAME))" \
--info2 "$(call Image/FileSystemStrip,$(IMAGE_ROOTFS))" \
$(call rootfspad/$(call Image/FileSystemStrip,$(IMAGE_ROOTFS))) \
$(CFE_EXTRAS) $(1)
endef
define Build/cfe-jffs2
$(STAGING_DIR_HOST)/bin/mkfs.jffs2 \
--big-endian \
--pad \
--no-cleanmarkers \
--eraseblock=$(patsubst %k,%KiB,$(BLOCKSIZE)) \
--root=$(1) \
--output=$@ \
--compression-mode=none
$(call Build/pad-to,$(BLOCKSIZE))
endef
define Build/cfe-jffs2-cferam
mv $@ $@.kernel
rm -rf $@-cferam
mkdir -p $@-cferam
# CFE ROM checks JFFS2 dirent version of cferam.
# If version is not > 0 it will ignore the fs entry.
# JFFS2 sets version 0 to the first fs entry and increments
# it on the following ones, so let's create a dummy file that
# will have version 0 and let cferam be the second (version 1).
touch $@-cferam/1-openwrt
# Add cferam as the last file in the JFFS2 partition
cp $(KDIR)/bcm63xx-cfe/$(CFE_RAM_FILE) $@-cferam/$(CFE_RAM_JFFS2_NAME)
# The JFFS2 partition creation should result in the following
# layout:
# 1) 1-openwrt (version 0, ino 2)
# 2) cferam.000 (version 1, ino 3)
$(call Build/cfe-jffs2,$@-cferam)
# Some devices need padding between CFE RAM and kernel
$(if $(CFE_RAM_JFFS2_PAD),$(call Build/pad-to,$(CFE_RAM_JFFS2_PAD)))
# Add CFE partition tag
$(if $(CFE_PART_ID),$(call Build/cfe-part-tag))
# Append kernel
dd if=$@.kernel >> $@
rm -f $@.kernel
endef
define Build/cfe-jffs2-kernel
rm -rf $@-kernel
mkdir -p $@-kernel
# CFE RAM checks JFFS2 dirent version of vmlinux.
# If version is not > 0 it will ignore the fs entry.
# JFFS2 sets version 0 to the first fs entry and increments
# it on the following ones, so let's create a dummy file that
# will have version 0 and let cferam be the second (version 1).
touch $@-kernel/1-openwrt
# vmlinux is located on a different JFFS2 partition, but CFE RAM
# ignores it, so let's create another dummy file that will match
# the JFFS2 ino of cferam entry on the first JFFS2 partition.
# CFE RAM won't be able to find vmlinux if cferam has the same
# ino as vmlinux.
touch $@-kernel/2-openwrt
# Add vmlinux as the last file in the JFFS2 partition
$(TOPDIR)/scripts/cfe-bin-header.py \
--input-file $@ \
--output-file $@-kernel/vmlinux.lz \
--load-addr $(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \
--entry-addr $(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY))
# The JFFS2 partition creation should result in the following
# layout:
# 1) 1-openwrt (version 0, ino 2)
# 2) 2-openwrt (version 1, ino 3)
# 3) vmlinux.lz (version 2, ino 4)
$(call Build/cfe-jffs2,$@-kernel)
endef
define Build/cfe-part-tag
mv $@ $@.part
$(TOPDIR)/scripts/cfe-partition-tag.py \
--input-file $@.part \
--output-file $@ \
--flags $(CFE_PART_FLAGS) \
--id $(CFE_PART_ID) \
--name $(VERSION_CODE) \
--version $(DEVICE_NAME)
$(call Build/pad-to,$(BLOCKSIZE))
dd if=$@.part >> $@
endef
define Build/cfe-sercomm-crypto
$(TOPDIR)/scripts/sercomm-crypto.py \
--input-file $@ \
--key-file $@.key \
--output-file $@.ser \
--version OpenWrt
$(STAGING_DIR_HOST)/bin/openssl enc -md md5 -aes-256-cbc \
-in $@ -out $@.enc \
-K `cat $@.key` \
-iv 00000000000000000000000000000000
dd if=$@.enc >> $@.ser
mv $@.ser $@
rm -f $@.enc $@.key
endef
define Build/cfe-sercomm-load
$(TOPDIR)/scripts/sercomm-payload.py \
--input-file $@ \
--output-file $@.new \
--pid "$(SERCOMM_PID)"
mv $@.new $@
endef
define Build/cfe-sercomm-part
$(TOPDIR)/scripts/sercomm-partition-tag.py \
--input-file $@ \
--output-file $@.kernel_rootfs \
--part-name kernel_rootfs \
--part-version OpenWrt \
--rootfs-version $(SERCOMM_VERSION)
rm -rf $@-rootfs_lib
mkdir -p $@-rootfs_lib
echo $(SERCOMM_VERSION) > $@-rootfs_lib/lib_ver
$(call Build/cfe-jffs2,$@-rootfs_lib)
$(call Build/pad-to,$(BLOCKSIZE))
$(TOPDIR)/scripts/sercomm-partition-tag.py \
--input-file $@ \
--output-file $@.rootfs_lib \
--part-name rootfs_lib \
--part-version $(SERCOMM_VERSION)
mv $@.kernel_rootfs $@
dd if=$@.rootfs_lib >> $@
endef
define Build/cfe-wfi-tag
$(TOPDIR)/scripts/cfe-wfi-tag.py \
--input-file $@ \
--output-file $@.new \
--version $(if $(1),$(1),$(CFE_WFI_VERSION)) \
--chip-id $(CFE_WFI_CHIP_ID) \
--flash-type $(CFE_WFI_FLASH_TYPE) \
$(if $(CFE_WFI_FLAGS),--flags $(CFE_WFI_FLAGS))
mv $@.new $@
endef
### Device scripts ###
define Device/Default
PROFILES = Default $$(DEVICE_NAME)
KERNEL_DEPENDS = $$(wildcard ../dts/$$(DEVICE_DTS).dts)
DEVICE_DTS_DIR := ../dts
CHIP_ID :=
SOC = bcm$$(CHIP_ID)
DEVICE_DTS = $$(SOC)-$(subst _,-,$(1))
DEVICE_LOADADDR :=
endef
ATH9K_PACKAGES := kmod-ath9k wpad-basic-wolfssl
B43_PACKAGES := kmod-b43 wpad-basic-wolfssl
USB1_PACKAGES := kmod-usb-ohci kmod-ledtrig-usbdev
USB2_PACKAGES := $(USB1_PACKAGES) kmod-usb2
include bcm63xx_$(SUBTARGET).mk
$(eval $(call BuildImage))

View File

@@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
DEVICE_VARS += CFE_BOARD_ID CFE_EXTRAS
DEVICE_VARS += FLASH_MB IMAGE_OFFSET
define Device/bcm63xx-cfe
FILESYSTEMS := squashfs jffs2-64k jffs2-128k
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-lzma elf
KERNEL_INITRAMFS_SUFFIX := .elf
IMAGES := cfe.bin sysupgrade.bin
IMAGE/cfe.bin := \
cfe-bin $$$$(if $$$$(FLASH_MB),--pad $$$$(shell expr $$$$(FLASH_MB) / 2))
IMAGE/sysupgrade.bin := cfe-bin | append-metadata
BLOCKSIZE := 0x10000
IMAGE_OFFSET :=
FLASH_MB :=
CFE_BOARD_ID :=
CFE_EXTRAS = --block-size $$(BLOCKSIZE) \
--image-offset $$(if $$(IMAGE_OFFSET),$$(IMAGE_OFFSET),$$(BLOCKSIZE))
endef
# Legacy CFEs with specific LZMA parameters and no length
define Device/bcm63xx-cfe-legacy
$(Device/bcm63xx-cfe)
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma-cfe
endef
define Device/comtrend_ar-5315u
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := AR-5315u
CHIP_ID := 6318
CFE_BOARD_ID := 96318A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5315u
define Device/comtrend_ar-5387un
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := AR-5387un
CHIP_ID := 6328
CFE_BOARD_ID := 96328A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5387un
define Device/comtrend_vr-3025u
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := VR-3025u
CHIP_ID := 6368
CFE_BOARD_ID := 96368M-1541N
BLOCKSIZE := 0x20000
FLASH_MB := 32
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
endef
TARGET_DEVICES += comtrend_vr-3025u
define Device/huawei_hg556a-b
$(Device/bcm63xx-cfe-legacy)
DEVICE_VENDOR := Huawei
DEVICE_MODEL := EchoLife HG556a
DEVICE_VARIANT := B
CHIP_ID := 6358
CFE_BOARD_ID := HW556
CFE_EXTRAS += --rsa-signature "EchoLife_HG556a" --tag-version 8
BLOCKSIZE := 0x20000
DEVICE_PACKAGES += $(USB2_PACKAGES) $(ATH9K_PACKAGES)
endef
TARGET_DEVICES += huawei_hg556a-b

View File

@@ -0,0 +1,81 @@
# SPDX-License-Identifier: GPL-2.0-or-later
DEVICE_VARS += CFE_PART_FLAGS CFE_PART_ID
DEVICE_VARS += CFE_RAM_FILE
DEVICE_VARS += CFE_RAM_JFFS2_NAME CFE_RAM_JFFS2_PAD
DEVICE_VARS += CFE_WFI_CHIP_ID CFE_WFI_FLASH_TYPE
DEVICE_VARS += CFE_WFI_FLAGS CFE_WFI_VERSION
DEVICE_VARS += SERCOMM_PID SERCOMM_VERSION
# CFE expects a single JFFS2 partition with cferam and kernel. However,
# it's possible to fool CFE into properly loading both cferam and kernel
# from two different JFFS2 partitions by adding dummy files (see
# cfe-jffs2-cferam and cfe-jffs2-kernel).
# Separate JFFS2 partitions allow upgrading openwrt without reflashing cferam
# JFFS2 partition, which is much safer in case anything goes wrong.
define Device/bcm63xx-nand
FILESYSTEMS := squashfs ubifs
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma | cfe-jffs2-kernel
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-lzma elf
KERNEL_INITRAMFS_SUFFIX := .elf
IMAGES := cfe.bin sysupgrade.bin
IMAGE/cfe.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) |\
cfe-jffs2-cferam | append-ubi | cfe-wfi-tag
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
KERNEL_SIZE := 5120k
CFE_PART_FLAGS :=
CFE_PART_ID :=
CFE_RAM_FILE :=
CFE_RAM_JFFS2_NAME :=
CFE_RAM_JFFS2_PAD :=
CFE_WFI_VERSION :=
CFE_WFI_CHIP_ID = 0x$$(CHIP_ID)
CFE_WFI_FLASH_TYPE :=
CFE_WFI_FLAGS :=
UBINIZE_OPTS := -E 5
DEVICE_PACKAGES += nand-utils
endef
define Device/sercomm-nand
$(Device/bcm63xx-nand)
IMAGES := factory.img sysupgrade.bin
IMAGE/factory.img := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi |\
cfe-sercomm-part | gzip | cfe-sercomm-load | cfe-sercomm-crypto
SERCOM_PID :=
SERCOMM_VERSION :=
endef
define Device/comtrend_vr-3032u
$(Device/bcm63xx-nand)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := VR-3032u
CHIP_ID := 63268
SOC := bcm63168
CFE_RAM_FILE := comtrend,vr-3032u/cferam.000
CFE_RAM_JFFS2_NAME := cferam.000
BLOCKSIZE := 128k
PAGESIZE := 2048
SUBPAGESIZE := 512
VID_HDR_OFFSET := 2048
DEVICE_PACKAGES += $(USB2_PACKAGES)
CFE_WFI_FLASH_TYPE := 3
CFE_WFI_VERSION := 0x5732
endef
TARGET_DEVICES += comtrend_vr-3032u
define Device/netgear_dgnd3700-v2
$(Device/bcm63xx-nand)
DEVICE_VENDOR := NETGEAR
DEVICE_MODEL := DGND3700
DEVICE_VARIANT := v2
CHIP_ID := 6362
CFE_RAM_FILE := netgear,dgnd3700-v2/cferam
CFE_RAM_JFFS2_NAME := cferam
CFE_RAM_JFFS2_PAD := 496k
BLOCKSIZE := 16k
PAGESIZE := 512
DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES)
CFE_WFI_FLASH_TYPE := 2
CFE_WFI_VERSION := 0x5731
endef
TARGET_DEVICES += netgear_dgnd3700-v2

View File

@@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
# Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
# Copyright (C) 2011 OpenWrt.org
# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
#
include $(TOPDIR)/rules.mk
LZMA_TEXT_START := 0x80a00000
LOADER := loader.bin
LOADER_NAME := $(basename $(notdir $(LOADER)))
LOADER_DATA :=
TARGET_DIR :=
UART_BASE_3329 := 0xb0000100
UART_BASE_3368 := 0xfff8c100
UART_BASE_3380 := 0xb4e00200
UART_BASE_3383 := 0xb4e00500
UART_BASE_3384 := 0xb4e00500
UART_BASE_6318 := 0xb0000100
UART_BASE_6328 := 0xb0000100
UART_BASE_6338 := 0xfffe0300
UART_BASE_6345 := 0xfffe0300
UART_BASE_6348 := 0xfffe0300
UART_BASE_6358 := 0xfffe0100
UART_BASE_6362 := 0xb0000100
UART_BASE_6368 := 0xb0000100
UART_BASE_63268 := 0xb0000180
UART_BASE_6816 := 0xb0000100
UART_BASE_6818 := 0xb0000100
UART_BASE_6828 := 0xb0000180
UART_BASE := $(if $(UART_BASE_$(CHIP_ID)),$(UART_BASE_$(CHIP_ID)),0)
ifeq ($(TARGET_DIR),)
TARGET_DIR := $(KDIR)
endif
LOADER_BIN := $(TARGET_DIR)/$(LOADER_NAME).bin
LOADER_ELF := $(TARGET_DIR)/$(LOADER_NAME).elf
PKG_NAME := lzma-loader
PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME)
.PHONY : loader-compile loader.bin loader.elf
$(PKG_BUILD_DIR)/.prepared:
mkdir $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
touch $@
loader-compile: $(PKG_BUILD_DIR)/.prepared
$(MAKE) -C $(PKG_BUILD_DIR) CROSS_COMPILE="$(TARGET_CROSS)" \
LZMA_TEXT_START=$(LZMA_TEXT_START) \
LOADER_DATA=$(LOADER_DATA) \
UART_BASE=$(UART_BASE) \
clean all
loader.elf: $(PKG_BUILD_DIR)/loader.elf
$(CP) $< $(LOADER_ELF)
loader.bin: $(PKG_BUILD_DIR)/loader.bin
$(CP) $< $(LOADER_BIN)
download:
prepare: $(PKG_BUILD_DIR)/.prepared
compile: loader-compile
install:
clean:
rm -rf $(PKG_BUILD_DIR)

View File

@@ -0,0 +1,584 @@
/*
LzmaDecode.c
LZMA Decoder (optimized for Speed version)
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this Code, expressly permits you to
statically or dynamically link your Code (or bind by name) to the
interfaces of this file without subjecting your linked Code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#include "LzmaDecode.h"
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*Buffer++)
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
#ifdef _LZMA_IN_CB
#define RC_TEST { if (Buffer == BufferLim) \
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
#else
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
#endif
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
{ int i = numLevels; res = 1; \
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
res -= (1 << numLevels); }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
unsigned char prop0;
if (size < LZMA_PROPERTIES_SIZE)
return LZMA_RESULT_DATA_ERROR;
prop0 = propsData[0];
if (prop0 >= (9 * 5 * 5))
return LZMA_RESULT_DATA_ERROR;
{
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
propsRes->lc = prop0;
/*
unsigned char remainder = (unsigned char)(prop0 / 9);
propsRes->lc = prop0 % 9;
propsRes->pb = remainder / 5;
propsRes->lp = remainder % 5;
*/
}
#ifdef _LZMA_OUT_READ
{
int i;
propsRes->DictionarySize = 0;
for (i = 0; i < 4; i++)
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
if (propsRes->DictionarySize == 0)
propsRes->DictionarySize = 1;
}
#endif
return LZMA_RESULT_OK;
}
#define kLzmaStreamWasFinishedId (-1)
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
CProb *p = vs->Probs;
SizeT nowPos = 0;
Byte previousByte = 0;
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
int lc = vs->Properties.lc;
#ifdef _LZMA_OUT_READ
UInt32 Range = vs->Range;
UInt32 Code = vs->Code;
#ifdef _LZMA_IN_CB
const Byte *Buffer = vs->Buffer;
const Byte *BufferLim = vs->BufferLim;
#else
const Byte *Buffer = inStream;
const Byte *BufferLim = inStream + inSize;
#endif
int state = vs->State;
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
int len = vs->RemainLen;
UInt32 globalPos = vs->GlobalPos;
UInt32 distanceLimit = vs->DistanceLimit;
Byte *dictionary = vs->Dictionary;
UInt32 dictionarySize = vs->Properties.DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
if (len == kLzmaStreamWasFinishedId)
return LZMA_RESULT_OK;
if (dictionarySize == 0)
{
dictionary = tempDictionary;
dictionarySize = 1;
tempDictionary[0] = vs->TempDictionary[0];
}
if (len == kLzmaNeedInitId)
{
{
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
UInt32 i;
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
rep0 = rep1 = rep2 = rep3 = 1;
state = 0;
globalPos = 0;
distanceLimit = 0;
dictionaryPos = 0;
dictionary[dictionarySize - 1] = 0;
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
}
len = 0;
}
while(len != 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
len--;
}
if (dictionaryPos == 0)
previousByte = dictionary[dictionarySize - 1];
else
previousByte = dictionary[dictionaryPos - 1];
#else /* if !_LZMA_OUT_READ */
int state = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
int len = 0;
const Byte *Buffer;
const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
{
UInt32 i;
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
}
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
#endif /* _LZMA_OUT_READ */
while(nowPos < outSize)
{
CProb *prob;
UInt32 bound;
int posState = (int)(
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& posStateMask);
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state >= kNumLitStates)
{
int matchByte;
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
#else
matchByte = outStream[nowPos - rep0];
#endif
do
{
int bit;
CProb *probLit;
matchByte <<= 1;
bit = (matchByte & 0x100);
probLit = prob + 0x100 + bit + symbol;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
}
while (symbol < 0x100)
{
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#endif
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
}
else
{
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
{
UpdateBit0(prob);
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < kNumLitStates ? 0 : 3;
prob = p + LenCoder;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG0 + state;
IfBit0(prob)
{
UpdateBit0(prob);
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
#ifdef _LZMA_OUT_READ
UInt32 pos;
#endif
UpdateBit0(prob);
#ifdef _LZMA_OUT_READ
if (distanceLimit == 0)
#else
if (nowPos == 0)
#endif
return LZMA_RESULT_DATA_ERROR;
state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
#endif
continue;
}
else
{
UpdateBit1(prob);
}
}
else
{
UInt32 distance;
UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2;
}
else
{
UpdateBit1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = p + RepLenCoder;
}
{
int numBits, offset;
CProb *probLen = prob + LenChoice;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
numBits = kLenNumHighBits;
}
}
RangeDecoderBitTreeDecode(probLen, numBits, len);
len += offset;
}
if (state < 4)
{
int posSlot;
state += kNumLitStates;
prob = p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = (2 | ((UInt32)posSlot & 1));
if (posSlot < kEndPosModelIndex)
{
rep0 <<= numDirectBits;
prob = p + SpecPos + rep0 - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
RC_NORMALIZE
Range >>= 1;
rep0 <<= 1;
if (Code >= Range)
{
Code -= Range;
rep0 |= 1;
}
}
while (--numDirectBits != 0);
prob = p + Align;
rep0 <<= kNumAlignBits;
numDirectBits = kNumAlignBits;
}
{
int i = 1;
int mi = 1;
do
{
CProb *prob3 = prob + mi;
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
i <<= 1;
}
while(--numDirectBits != 0);
}
}
else
rep0 = posSlot;
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
#ifdef _LZMA_OUT_READ
if (rep0 > distanceLimit)
#else
if (rep0 > nowPos)
#endif
return LZMA_RESULT_DATA_ERROR;
#ifdef _LZMA_OUT_READ
if (dictionarySize - distanceLimit > (UInt32)len)
distanceLimit += len;
else
distanceLimit = dictionarySize;
#endif
do
{
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
len--;
outStream[nowPos++] = previousByte;
}
while(len != 0 && nowPos < outSize);
}
}
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + (UInt32)nowPos;
vs->DistanceLimit = distanceLimit;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->Reps[3] = rep3;
vs->State = state;
vs->RemainLen = len;
vs->TempDictionary[0] = tempDictionary[0];
#endif
#ifdef _LZMA_IN_CB
vs->Buffer = Buffer;
vs->BufferLim = BufferLim;
#else
*inSizeProcessed = (SizeT)(Buffer - inStream);
#endif
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}

View File

@@ -0,0 +1,113 @@
/*
LzmaDecode.h
LZMA Decoder interface
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#ifndef __LZMADECODE_H
#define __LZMADECODE_H
#include "LzmaTypes.h"
/* #define _LZMA_IN_CB */
/* Use callback for input data */
/* #define _LZMA_OUT_READ */
/* Use read function for output data */
/* #define _LZMA_PROB32 */
/* It can increase speed on some 32-bit CPUs,
but memory usage will be doubled in that case */
/* #define _LZMA_LOC_OPT */
/* Enable local speed optimizations inside code */
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#ifdef _LZMA_IN_CB
typedef struct _ILzmaInCallback
{
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
} ILzmaInCallback;
#endif
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
typedef struct _CLzmaProperties
{
int lc;
int lp;
int pb;
#ifdef _LZMA_OUT_READ
UInt32 DictionarySize;
#endif
}CLzmaProperties;
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
#define kLzmaNeedInitId (-2)
typedef struct _CLzmaDecoderState
{
CLzmaProperties Properties;
CProb *Probs;
#ifdef _LZMA_IN_CB
const unsigned char *Buffer;
const unsigned char *BufferLim;
#endif
#ifdef _LZMA_OUT_READ
unsigned char *Dictionary;
UInt32 Range;
UInt32 Code;
UInt32 DictionaryPos;
UInt32 GlobalPos;
UInt32 DistanceLimit;
UInt32 Reps[4];
int State;
int RemainLen;
unsigned char TempDictionary[4];
#endif
} CLzmaDecoderState;
#ifdef _LZMA_OUT_READ
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
#endif
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
#endif

View File

@@ -0,0 +1,45 @@
/*
LzmaTypes.h
Types for LZMA Decoder
This file written and distributed to public domain by Igor Pavlov.
This file is part of LZMA SDK 4.40 (2006-05-01)
*/
#ifndef __LZMATYPES_H
#define __LZMATYPES_H
#ifndef _7ZIP_BYTE_DEFINED
#define _7ZIP_BYTE_DEFINED
typedef unsigned char Byte;
#endif
#ifndef _7ZIP_UINT16_DEFINED
#define _7ZIP_UINT16_DEFINED
typedef unsigned short UInt16;
#endif
#ifndef _7ZIP_UINT32_DEFINED
#define _7ZIP_UINT32_DEFINED
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
/* #define _LZMA_NO_SYSTEM_SIZE_T */
/* You can use it, if you don't want <stddef.h> */
#ifndef _7ZIP_SIZET_DEFINED
#define _7ZIP_SIZET_DEFINED
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
#include <stddef.h>
typedef size_t SizeT;
#endif
#endif
#endif

View File

@@ -0,0 +1,85 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Makefile for the LZMA compressed kernel loader for BMIPS based boards
#
# Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
# Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
#
# Some parts of this file was based on the OpenWrt specific lzma-loader
# for the BCM47xx and ADM5120 based boards:
# Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
# Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
# Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
#
LOADER_ADDR :=
KERNEL_ADDR :=
LZMA_TEXT_START := 0x80a00000
LOADER_DATA :=
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
BIN_FLAGS := -O binary -R .reginfo -R .note -R .comment -R .mdebug \
-R .MIPS.abiflags -S
CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
-fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 \
-mno-abicalls -fno-pic -ffunction-sections -pipe \
-ffreestanding -fhonour-copts \
-mabi=32 -march=mips32 \
-Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
CFLAGS += -D_LZMA_PROB32
CFLAGS += -DUART_BASE=$(UART_BASE)
ASFLAGS = $(CFLAGS) -D__ASSEMBLY__
LDFLAGS = -static --gc-sections -no-warn-mismatch
LDFLAGS += -e startup -T loader.lds -Ttext $(LZMA_TEXT_START)
O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
OBJECTS := head.o loader.o cache.o board.o printf.o LzmaDecode.o
ifneq ($(strip $(LOADER_DATA)),)
OBJECTS += data.o
CFLAGS += -DLZMA_WRAPPER=1 -DLOADADDR=$(KERNEL_ADDR)
endif
all: loader.elf
# Don't build dependencies, this may die if $(CC) isn't gcc
dep:
install:
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o : %.S
$(CC) $(ASFLAGS) -c -o $@ $<
data.o: $(LOADER_DATA)
$(LD) -r -b binary --oformat $(O_FORMAT) -T lzma-data.lds -o $@ $<
loader: $(OBJECTS)
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
loader.bin: loader
$(OBJCOPY) $(BIN_FLAGS) $< $@
loader2.o: loader.bin
$(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $<
loader.elf: loader2.o
$(LD) -e startup -T loader2.lds -Ttext $(LOADER_ADDR) -o $@ $<
mrproper: clean
clean:
rm -f loader *.elf *.bin *.o

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM63XX specific implementation parts
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
*/
#include <stddef.h>
#include "config.h"
#define READREG(r) *(volatile unsigned int *)(r)
#define WRITEREG(r,v) *(volatile unsigned int *)(r) = v
#define UART_IR_REG 0x10
#define UART_FIFO_REG 0x14
static void wait_xfered(void)
{
unsigned int val;
do {
val = READREG(UART_BASE + UART_IR_REG);
if (val & (1 << 5))
break;
} while (1);
}
void board_putc(int ch)
{
if (!UART_BASE)
return;
wait_xfered();
WRITEREG(UART_BASE + UART_FIFO_REG, ch);
wait_xfered();
}

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* The cache manipulation routine has been taken from the U-Boot project.
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
*/
#include "cache.h"
#include "cacheops.h"
#include "config.h"
#include "printf.h"
#define cache_op(op,addr) \
__asm__ __volatile__( \
" .set push \n" \
" .set noreorder \n" \
" .set mips3\n\t \n" \
" cache %0, %1 \n" \
" .set pop \n" \
: \
: "i" (op), "R" (*(unsigned char *)(addr)))
void flush_cache(unsigned long start_addr, unsigned long size)
{
unsigned long lsize = CONFIG_CACHELINE_SIZE;
unsigned long addr = start_addr & ~(lsize - 1);
unsigned long aend = (start_addr + size + (lsize - 1)) & ~(lsize - 1);
printf("blasting from 0x%08x to 0x%08x (0x%08x - 0x%08x)\n", start_addr, size, addr, aend);
while (1) {
cache_op(Hit_Writeback_Inv_D, addr);
cache_op(Hit_Invalidate_I, addr);
if (addr == aend)
break;
addr += lsize;
}
}

View File

@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*/
#ifndef __CACHE_H
#define __CACHE_H
void flush_cache(unsigned long start_addr, unsigned long size);
#endif /* __CACHE_H */

View File

@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Cache operations for the cache instruction.
*
* (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle
* (C) Copyright 1999 Silicon Graphics, Inc.
*/
#ifndef __ASM_CACHEOPS_H
#define __ASM_CACHEOPS_H
/*
* Cache Operations available on all MIPS processors with R4000-style caches
*/
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
#define Index_Load_Tag_I 0x04
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
#if defined(CONFIG_CPU_LOONGSON2)
#define Hit_Invalidate_I 0x00
#else
#define Hit_Invalidate_I 0x10
#endif
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
/*
* R4000-specific cacheops
*/
#define Create_Dirty_Excl_D 0x0d
#define Fill 0x14
#define Hit_Writeback_I 0x18
#define Hit_Writeback_D 0x19
/*
* R4000SC and R4400SC-specific cacheops
*/
#define Index_Invalidate_SI 0x02
#define Index_Writeback_Inv_SD 0x03
#define Index_Load_Tag_SI 0x06
#define Index_Load_Tag_SD 0x07
#define Index_Store_Tag_SI 0x0A
#define Index_Store_Tag_SD 0x0B
#define Create_Dirty_Excl_SD 0x0f
#define Hit_Invalidate_SI 0x12
#define Hit_Invalidate_SD 0x13
#define Hit_Writeback_Inv_SD 0x17
#define Hit_Writeback_SD 0x1b
#define Hit_Set_Virtual_SI 0x1e
#define Hit_Set_Virtual_SD 0x1f
/*
* R5000-specific cacheops
*/
#define R5K_Page_Invalidate_S 0x17
/*
* RM7000-specific cacheops
*/
#define Page_Invalidate_T 0x16
/*
* R10000-specific cacheops
*
* Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
* Most of the _S cacheops are identical to the R4000SC _SD cacheops.
*/
#define Index_Writeback_Inv_S 0x03
#define Index_Load_Tag_S 0x07
#define Index_Store_Tag_S 0x0B
#define Hit_Invalidate_S 0x13
#define Cache_Barrier 0x14
#define Hit_Writeback_Inv_S 0x17
#define Index_Load_Data_I 0x18
#define Index_Load_Data_D 0x19
#define Index_Load_Data_S 0x1b
#define Index_Store_Data_I 0x1c
#define Index_Store_Data_D 0x1d
#define Index_Store_Data_S 0x1f
#endif /* __ASM_CACHEOPS_H */

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define CONFIG_ICACHE_SIZE (32 * 1024)
#define CONFIG_DCACHE_SIZE (32 * 1024)
#define CONFIG_CACHELINE_SIZE 16
#endif /* _CONFIG_H_ */

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
*
* Copyright (C) 2001, Monta Vista Software
* Author: jsun@mvista.com or jsun@junsun.net
*/
#ifndef _cp0regdef_h_
#define _cp0regdef_h_
#define CP0_INDEX $0
#define CP0_RANDOM $1
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_BADVADDR $8
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
#define CP0_STATUS $12
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
#define CP0_CONFIG $16
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
#define CP0_XCONTEXT $20
#define CP0_FRAMEMASK $21
#define CP0_DIAGNOSTIC $22
#define CP0_PERFORMANCE $25
#define CP0_ECC $26
#define CP0_CACHEERR $27
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CP0_ERROREPC $30
#define read_32bit_c0_register(reg,sel) \
({ int __res; \
if (sel == 0) \
__asm__ __volatile__( \
"mfc0\t%0, " #reg "\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mfc0\t%0, " #reg ", " #sel "\n\t" \
".set mips0\n\t" \
: "=r" (__res)); \
__res; \
})
#endif

View File

@@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Some parts of this code was based on the OpenWrt specific lzma-loader
* for the BCM47xx and ADM5120 based boards:
* Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*/
#include <asm/asm.h>
#include <asm/regdef.h>
#include "cp0regdef.h"
#include "cacheops.h"
#include "config.h"
#define KSEG0 0x80000000
.macro ehb
sll zero, 3
.endm
.text
LEAF(startup)
.set noreorder
.set mips32
mtc0 zero, CP0_WATCHLO # clear watch registers
mtc0 zero, CP0_WATCHHI
mtc0 zero, CP0_CAUSE # clear before writing status register
mfc0 t0, CP0_STATUS
li t1, 0x1000001f
or t0, t1
xori t0, 0x1f
mtc0 t0, CP0_STATUS
ehb
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
ehb
la t0, __reloc_label # get linked address of label
bal __reloc_label # branch and link to label to
nop # get actual address
__reloc_label:
subu t0, ra, t0 # get reloc_delta
beqz t0, __reloc_done # if delta is 0 we are in the right place
nop
/* Copy our code to the right place */
la t1, _code_start # get linked address of _code_start
la t2, _code_end # get linked address of _code_end
addu t0, t0, t1 # calculate actual address of _code_start
__reloc_copy:
lw t3, 0(t0)
sw t3, 0(t1)
add t1, 4
blt t1, t2, __reloc_copy
add t0, 4
/* flush cache */
la t0, _code_start
la t1, _code_end
li t2, ~(CONFIG_CACHELINE_SIZE - 1)
and t0, t2
and t1, t2
li t2, CONFIG_CACHELINE_SIZE
b __flush_check
nop
__flush_line:
cache Hit_Writeback_Inv_D, 0(t0)
cache Hit_Invalidate_I, 0(t0)
add t0, t2
__flush_check:
bne t0, t1, __flush_line
nop
sync
__reloc_done:
/* clear bss */
la t0, _bss_start
la t1, _bss_end
b __bss_check
nop
__bss_fill:
sw zero, 0(t0)
addi t0, 4
__bss_check:
bne t0, t1, __bss_fill
nop
/* Setup new "C" stack */
la sp, _stack
/* reserve stack space for a0-a3 registers */
subu sp, 16
/* jump to the decompressor routine */
la t0, loader_main
jr t0
nop
.set reorder
END(startup)

View File

@@ -0,0 +1,169 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Some parts of this code was based on the OpenWrt specific lzma-loader
* for the BCM47xx and ADM5120 based boards:
* Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
* Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*
* The image_header structure has been taken from the U-Boot project.
* (C) Copyright 2008 Semihalf
* (C) Copyright 2000-2005
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <stddef.h>
#include <stdint.h>
#include "config.h"
#include "cache.h"
#include "printf.h"
#include "LzmaDecode.h"
#define KSEG0 0x80000000
#define KSEG1 0xa0000000
#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
#undef LZMA_DEBUG
#ifdef LZMA_DEBUG
# define DBG(f, a...) printf(f, ## a)
#else
# define DBG(f, a...) do {} while (0)
#endif
/* beyond the image end, size not known in advance */
extern unsigned char workspace[];
static CLzmaDecoderState lzma_state;
static unsigned char *lzma_data;
static unsigned long lzma_datasize;
static unsigned long lzma_outsize;
static unsigned long kernel_la;
static void halt(void)
{
printf("\nSystem halted!\n");
for(;;);
}
static __inline__ unsigned char lzma_get_byte(void)
{
unsigned char c;
lzma_datasize--;
c = *lzma_data++;
return c;
}
static int lzma_init_props(void)
{
unsigned char props[LZMA_PROPERTIES_SIZE];
int res;
int i;
/* read lzma properties */
for (i = 0; i < LZMA_PROPERTIES_SIZE; i++)
props[i] = lzma_get_byte();
/* read the lower half of uncompressed size in the header */
lzma_outsize = ((SizeT) lzma_get_byte()) +
((SizeT) lzma_get_byte() << 8) +
((SizeT) lzma_get_byte() << 16) +
((SizeT) lzma_get_byte() << 24);
/* skip rest of the header (upper half of uncompressed size) */
for (i = 0; i < 4; i++)
lzma_get_byte();
res = LzmaDecodeProperties(&lzma_state.Properties, props,
LZMA_PROPERTIES_SIZE);
return res;
}
static int lzma_decompress(unsigned char *outStream)
{
SizeT ip, op;
int ret;
lzma_state.Probs = (CProb *) workspace;
ret = LzmaDecode(&lzma_state, lzma_data, lzma_datasize, &ip, outStream,
lzma_outsize, &op);
if (ret != LZMA_RESULT_OK) {
int i;
DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n",
ret, lzma_data + ip, lzma_outsize, ip, op);
for (i = 0; i < 16; i++)
DBG("%02x ", lzma_data[ip + i]);
DBG("\n");
}
return ret;
}
static void lzma_init_data(void)
{
extern unsigned char _lzma_data_start[];
extern unsigned char _lzma_data_end[];
kernel_la = LOADADDR;
lzma_data = _lzma_data_start;
lzma_datasize = _lzma_data_end - _lzma_data_start;
}
void loader_main(unsigned long reg_a0, unsigned long reg_a1,
unsigned long reg_a2, unsigned long reg_a3)
{
void (*kernel_entry) (unsigned long, unsigned long, unsigned long,
unsigned long);
int res;
printf("\n\nOpenWrt kernel loader for BMIPS\n");
printf("Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>\n");
printf("Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>\n");
printf("Copyright (C) 2020 Alvaro Fernandez Rojas <noltari@gmail.com>\n");
lzma_init_data();
res = lzma_init_props();
if (res != LZMA_RESULT_OK) {
printf("Incorrect LZMA stream properties!\n");
halt();
}
printf("Decompressing kernel... ");
res = lzma_decompress((unsigned char *) kernel_la);
if (res != LZMA_RESULT_OK) {
printf("failed, ");
switch (res) {
case LZMA_RESULT_DATA_ERROR:
printf("data error!\n");
break;
default:
printf("unknown error %d!\n", res);
}
halt();
} else {
printf("done!\n");
}
flush_cache(kernel_la, lzma_outsize);
printf("Starting kernel at %08x...\n\n", kernel_la);
kernel_entry = (void *) kernel_la;
kernel_entry(reg_a0, reg_a1, reg_a2, reg_a3);
}

View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.text : {
_code_start = .;
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.data.lzma)
}
. = ALIGN(32);
.data : {
*(.data)
*(.data.*)
}
. = ALIGN(32);
_code_end = .;
_bss_start = .;
.bss : {
*(.bss)
*(.bss.*)
}
. = ALIGN(32);
_bss_end = .;
. = . + 8192;
_stack = .;
workspace = .;
}

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.text : {
startup = .;
*(.text)
*(.text.*)
*(.data)
*(.data.*)
}
}

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.data.lzma : {
_lzma_data_start = .;
*(.data)
_lzma_data_end = .;
}
}

View File

@@ -0,0 +1,345 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*/
#include "printf.h"
extern void board_putc(int ch);
/* this is the maximum width for a variable */
#define LP_MAX_BUF 256
/* macros */
#define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') )
#define Ctod(x) ( (x) - '0')
/* forward declaration */
static int PrintChar(char *, char, int, int);
static int PrintString(char *, char *, int, int);
static int PrintNum(char *, unsigned long, int, int, int, int, char, int);
/* private variable */
static const char theFatalMsg[] = "fatal error in lp_Print!";
/* -*-
* A low level printf() function.
*/
static void
lp_Print(void (*output)(void *, char *, int),
void * arg,
char *fmt,
va_list ap)
{
#define OUTPUT(arg, s, l) \
{ if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
(*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
} else { \
(*output)(arg, s, l); \
} \
}
char buf[LP_MAX_BUF];
char c;
char *s;
long int num;
int longFlag;
int negFlag;
int width;
int prec;
int ladjust;
char padc;
int length;
for(;;) {
{
/* scan for the next '%' */
char *fmtStart = fmt;
while ( (*fmt != '\0') && (*fmt != '%')) {
fmt ++;
}
/* flush the string found so far */
OUTPUT(arg, fmtStart, fmt-fmtStart);
/* are we hitting the end? */
if (*fmt == '\0') break;
}
/* we found a '%' */
fmt ++;
/* check for long */
if (*fmt == 'l') {
longFlag = 1;
fmt ++;
} else {
longFlag = 0;
}
/* check for other prefixes */
width = 0;
prec = -1;
ladjust = 0;
padc = ' ';
if (*fmt == '-') {
ladjust = 1;
fmt ++;
}
if (*fmt == '0') {
padc = '0';
fmt++;
}
if (IsDigit(*fmt)) {
while (IsDigit(*fmt)) {
width = 10 * width + Ctod(*fmt++);
}
}
if (*fmt == '.') {
fmt ++;
if (IsDigit(*fmt)) {
prec = 0;
while (IsDigit(*fmt)) {
prec = prec*10 + Ctod(*fmt++);
}
}
}
/* check format flag */
negFlag = 0;
switch (*fmt) {
case 'b':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'd':
case 'D':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
if (num < 0) {
num = - num;
negFlag = 1;
}
length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'o':
case 'O':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'u':
case 'U':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'x':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'X':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
OUTPUT(arg, buf, length);
break;
case 'c':
c = (char)va_arg(ap, int);
length = PrintChar(buf, c, width, ladjust);
OUTPUT(arg, buf, length);
break;
case 's':
s = (char*)va_arg(ap, char *);
length = PrintString(buf, s, width, ladjust);
OUTPUT(arg, buf, length);
break;
case '\0':
fmt --;
break;
default:
/* output this char as it is */
OUTPUT(arg, fmt, 1);
} /* switch (*fmt) */
fmt ++;
} /* for(;;) */
/* special termination call */
OUTPUT(arg, "\0", 1);
}
/* --------------- local help functions --------------------- */
static int
PrintChar(char * buf, char c, int length, int ladjust)
{
int i;
if (length < 1) length = 1;
if (ladjust) {
*buf = c;
for (i=1; i< length; i++) buf[i] = ' ';
} else {
for (i=0; i< length-1; i++) buf[i] = ' ';
buf[length - 1] = c;
}
return length;
}
static int
PrintString(char * buf, char* s, int length, int ladjust)
{
int i;
int len=0;
char* s1 = s;
while (*s1++) len++;
if (length < len) length = len;
if (ladjust) {
for (i=0; i< len; i++) buf[i] = s[i];
for (i=len; i< length; i++) buf[i] = ' ';
} else {
for (i=0; i< length-len; i++) buf[i] = ' ';
for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
}
return length;
}
static int
PrintNum(char * buf, unsigned long u, int base, int negFlag,
int length, int ladjust, char padc, int upcase)
{
/* algorithm :
* 1. prints the number from left to right in reverse form.
* 2. fill the remaining spaces with padc if length is longer than
* the actual length
* TRICKY : if left adjusted, no "0" padding.
* if negtive, insert "0" padding between "0" and number.
* 3. if (!ladjust) we reverse the whole string including paddings
* 4. otherwise we only reverse the actual string representing the num.
*/
int actualLength =0;
char *p = buf;
int i;
do {
int tmp = u %base;
if (tmp <= 9) {
*p++ = '0' + tmp;
} else if (upcase) {
*p++ = 'A' + tmp - 10;
} else {
*p++ = 'a' + tmp - 10;
}
u /= base;
} while (u != 0);
if (negFlag) {
*p++ = '-';
}
/* figure out actual length and adjust the maximum length */
actualLength = p - buf;
if (length < actualLength) length = actualLength;
/* add padding */
if (ladjust) {
padc = ' ';
}
if (negFlag && !ladjust && (padc == '0')) {
for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
buf[length -1] = '-';
} else {
for (i = actualLength; i< length; i++) buf[i] = padc;
}
/* prepare to reverse the string */
{
int begin = 0;
int end;
if (ladjust) {
end = actualLength - 1;
} else {
end = length -1;
}
while (end > begin) {
char tmp = buf[begin];
buf[begin] = buf[end];
buf[end] = tmp;
begin ++;
end --;
}
}
/* adjust the string pointer */
return length;
}
static void printf_output(void *arg, char *s, int l)
{
int i;
// special termination call
if ((l==1) && (s[0] == '\0')) return;
for (i=0; i< l; i++) {
board_putc(s[i]);
if (s[i] == '\n') board_putc('\r');
}
}
void printf(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lp_Print(printf_output, 0, fmt, ap);
va_end(ap);
}

View File

@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*/
#ifndef _printf_h_
#define _printf_h_
#include <stdarg.h>
void printf(char *fmt, ...);
#endif /* _printf_h_ */