mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-15 18:03:30 +00:00
ramips/mt7621: Add HATLab GateBoard-One Support
Signed-off-by: Aodzip <aodzip@gmail.com> Signed-off-by: AnYun <amadeus@openjmu.xyz>
This commit is contained in:
parent
ea9e965d33
commit
3302e26e94
54
package/system/rdloader/Makefile
Normal file
54
package/system/rdloader/Makefile
Normal file
@ -0,0 +1,54 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=rdloader
|
||||
PKG_VERSION:=1.0.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_BUILD_DEPENDS:=util-linux e2fsprogs
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/rdloader
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=kmod loader for ramdisk enviroment
|
||||
DEPENDS:=@TARGET_ramips +e2fsprogs +libblkid
|
||||
endef
|
||||
|
||||
define Package/rdloader/description
|
||||
Lightweight kmod loader for ramdisk enviroment,
|
||||
support uuid-based rootfs mount
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
CMAKE_OPTIONS += -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
define Build/InstallDev
|
||||
rm -fR $(STAGING_DIR)/rdloader
|
||||
mkdir -p $(STAGING_DIR)/rdloader/{bin,lib,etc}
|
||||
|
||||
$(CP) $(PKG_BUILD_DIR)/rdloader $(STAGING_DIR)/rdloader/bin/
|
||||
$(CP) $(STAGING_DIR_ROOT)/usr/sbin/e2fsck $(STAGING_DIR)/rdloader/bin/
|
||||
$(CP) $(STAGING_DIR_ROOT)/etc/e2fsck.conf $(STAGING_DIR)/rdloader/etc/
|
||||
|
||||
( \
|
||||
export \
|
||||
READELF=$(TARGET_CROSS)readelf \
|
||||
OBJCOPY=$(TARGET_CROSS)objcopy \
|
||||
XARGS="$(XARGS)"; \
|
||||
find $(STAGING_DIR)/rdloader/bin/ -type f -a -exec \
|
||||
$(SCRIPT_DIR)/gen-rddependencies.sh {} \; ; \
|
||||
) | while read FILE; do \
|
||||
cp $(STAGING_DIR_ROOT)/lib/$$$$FILE $(STAGING_DIR)/rdloader/lib/ || \
|
||||
cp $(STAGING_DIR_ROOT)/usr/lib/$$$$FILE $(STAGING_DIR)/rdloader/lib/ \
|
||||
; \
|
||||
done;
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,rdloader))
|
9
package/system/rdloader/src/CMakeLists.txt
Normal file
9
package/system/rdloader/src/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
project(rdloader C)
|
||||
|
||||
add_executable(rdloader main.c insmod.c insmod.h mknod.c mknod.h mkdev_node.c mkdev_node.h blkid2.c blkid2.h cmdline.c cmdline.h switch_root.c switch_root.h)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} blkid)
|
||||
|
||||
install(TARGETS rdloader RUNTIME DESTINATION /usr/sbin)
|
40
package/system/rdloader/src/blkid2.c
Normal file
40
package/system/rdloader/src/blkid2.c
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by juno on 2022/1/11.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <blkid/blkid.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "blkid2.h"
|
||||
|
||||
int get_blkid(const char *blkdev, char **uuid)
|
||||
{
|
||||
blkid_probe pr;
|
||||
int ret;
|
||||
size_t len;
|
||||
const char *data;
|
||||
void *out;
|
||||
|
||||
pr = blkid_new_probe_from_filename(blkdev);
|
||||
if (!pr)
|
||||
{
|
||||
fprintf(stderr, "Failed open %s:%s\n", blkdev, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
blkid_do_probe(pr);
|
||||
ret = blkid_probe_lookup_value(pr, "UUID", &data, &len);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
out = calloc(1, len + 1);
|
||||
memcpy(out, data, len);
|
||||
*uuid = out;
|
||||
}
|
||||
|
||||
blkid_free_probe(pr);
|
||||
|
||||
return ret;
|
||||
}
|
10
package/system/rdloader/src/blkid2.h
Normal file
10
package/system/rdloader/src/blkid2.h
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by juno on 2022/1/11.
|
||||
//
|
||||
|
||||
#ifndef INIT_BLKID2_H
|
||||
#define INIT_BLKID2_H
|
||||
|
||||
int get_blkid(const char *blkdev, char **uuid);
|
||||
|
||||
#endif //INIT_BLKID2_H
|
209
package/system/rdloader/src/cmdline.c
Normal file
209
package/system/rdloader/src/cmdline.c
Normal file
@ -0,0 +1,209 @@
|
||||
//
|
||||
// Created by juno on 2022/1/11.
|
||||
//
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
static void insert_fstype_tail(struct fstype **head, struct fstype *fs)
|
||||
{
|
||||
struct fstype *curr = *head;
|
||||
struct fstype *next = NULL;
|
||||
|
||||
if (!curr)
|
||||
{
|
||||
*head = fs;
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
next = curr->next;
|
||||
if (!next)
|
||||
{
|
||||
curr->next = fs;
|
||||
break;
|
||||
}
|
||||
curr = next;
|
||||
} while (curr);
|
||||
}
|
||||
|
||||
static int parse_root(char *args, char **ret)
|
||||
{
|
||||
char *root = NULL;
|
||||
|
||||
if (!args)
|
||||
return -1;
|
||||
|
||||
if (strstr(args, "PARTUUID=") != NULL)
|
||||
{
|
||||
root = strtok(args, "=");
|
||||
root = strtok(NULL, "=");
|
||||
root = strtok(NULL, "=");
|
||||
if (!root)
|
||||
return -1;
|
||||
|
||||
asprintf(ret, "/dev/disk/by-partuuid/%s", root);
|
||||
}
|
||||
else if (strstr(args, "UUID=") != NULL)
|
||||
{
|
||||
|
||||
root = strtok(args, "=");
|
||||
root = strtok(NULL, "=");
|
||||
root = strtok(NULL, "=");
|
||||
|
||||
if (!root)
|
||||
return -1;
|
||||
|
||||
asprintf(ret, "/dev/disk/by-uuid/%s", root);
|
||||
}
|
||||
else if (strstr(args, "/dev/"))
|
||||
{
|
||||
*ret = strdup(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
asprintf(ret, "/dev/%s", args);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fstype *parse_rootfs(char **fstype_list)
|
||||
{
|
||||
struct fstype *ret = NULL;
|
||||
char *list = *fstype_list;
|
||||
struct fstype *default_fs = NULL;
|
||||
struct fstype *fs = NULL;
|
||||
|
||||
if (list)
|
||||
{
|
||||
list = strtok(list, "=");
|
||||
|
||||
while ((list = strtok(NULL, ",")))
|
||||
{
|
||||
fs = calloc(1, sizeof(struct fstype));
|
||||
|
||||
if (!fs)
|
||||
return NULL;
|
||||
|
||||
fs->name = strdup(list);
|
||||
insert_fstype_tail(&ret, fs);
|
||||
}
|
||||
}
|
||||
|
||||
default_fs = calloc(1, sizeof(struct fstype));
|
||||
default_fs->name = strdup("ext4");
|
||||
insert_fstype_tail(&ret, default_fs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int parse_cmdline(struct bootargs_t **ret)
|
||||
{
|
||||
FILE *fp;
|
||||
char *cmdline = NULL;
|
||||
struct fstype *fs = NULL;
|
||||
char str[1024] = {0};
|
||||
char *root = NULL;
|
||||
char *rootfs = NULL;
|
||||
struct bootargs_t *bootargs = NULL;
|
||||
|
||||
fp = fopen("/proc/cmdline", "r");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
fprintf(stderr, "get cmdline failed:%s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fgets(str, sizeof(str) - 1, fp) == NULL)
|
||||
{
|
||||
fprintf(stderr, "cmdline empty\n");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
cmdline = strtok(str, " ");
|
||||
|
||||
do
|
||||
{
|
||||
if (!cmdline)
|
||||
continue;
|
||||
|
||||
if (strstr(cmdline, "root="))
|
||||
root = cmdline;
|
||||
if (strstr(cmdline, "rootfstype="))
|
||||
rootfs = cmdline;
|
||||
|
||||
} while ((cmdline = strtok(NULL, " ")) != NULL);
|
||||
|
||||
if (parse_root(root, &root) < 0)
|
||||
{
|
||||
fprintf(stderr, "root args error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fs = parse_rootfs(&rootfs)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "fstype error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bootargs = calloc(1, sizeof(struct bootargs_t));
|
||||
|
||||
if (!bootargs)
|
||||
{
|
||||
fprintf(stderr, "alloc bootargs failed\n");
|
||||
free(fs);
|
||||
free(root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bootargs->root = root;
|
||||
bootargs->fstype = fs;
|
||||
|
||||
*ret = bootargs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_bootargs(struct bootargs_t **args)
|
||||
{
|
||||
struct bootargs_t *bootargs = *args;
|
||||
struct fstype *curr = NULL;
|
||||
struct fstype *next = NULL;
|
||||
|
||||
if (!bootargs)
|
||||
return;
|
||||
|
||||
if (bootargs->root)
|
||||
free(bootargs->root);
|
||||
|
||||
curr = bootargs->fstype;
|
||||
|
||||
do
|
||||
{
|
||||
if (curr)
|
||||
{
|
||||
if (curr->name)
|
||||
free(curr->name);
|
||||
|
||||
next = curr->next;
|
||||
free(curr);
|
||||
}
|
||||
|
||||
curr = next;
|
||||
|
||||
} while (curr);
|
||||
|
||||
free(bootargs);
|
||||
}
|
24
package/system/rdloader/src/cmdline.h
Normal file
24
package/system/rdloader/src/cmdline.h
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by juno on 2022/1/11.
|
||||
//
|
||||
|
||||
#ifndef INIT_CMDLINE_H
|
||||
#define INIT_CMDLINE_H
|
||||
|
||||
struct fstype
|
||||
{
|
||||
char *name;
|
||||
struct fstype *next;
|
||||
};
|
||||
|
||||
struct bootargs_t
|
||||
{
|
||||
char *root;
|
||||
struct fstype *fstype;
|
||||
};
|
||||
|
||||
int parse_cmdline(struct bootargs_t **ret);
|
||||
|
||||
void free_bootargs(struct bootargs_t **args);
|
||||
|
||||
#endif //INIT_CMDLINE_H
|
161
package/system/rdloader/src/insmod.c
Normal file
161
package/system/rdloader/src/insmod.c
Normal file
@ -0,0 +1,161 @@
|
||||
//
|
||||
// Created by juno on 2022/1/7.
|
||||
//
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <byteswap.h>
|
||||
#include <limits.h>
|
||||
#include "insmod.h"
|
||||
|
||||
#define init_module(module, len, opts) syscall(__NR_init_module, module, len, opts)
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define SWAP_BE32(x) (x)
|
||||
#define SWAP_BE64(x) (x)
|
||||
#else
|
||||
#define SWAP_BE32(x) bswap_32(x)
|
||||
#define SWAP_BE64(x) bswap_64(x)
|
||||
#endif
|
||||
|
||||
static char *parse_cmdline_module_options(const char **argv, int quote_space)
|
||||
{
|
||||
char *options;
|
||||
int optlen;
|
||||
|
||||
options = calloc(1, sizeof(char));
|
||||
optlen = 0;
|
||||
|
||||
while (*++argv)
|
||||
{
|
||||
const char *fmt;
|
||||
const char *var;
|
||||
const char *val;
|
||||
|
||||
var = *argv;
|
||||
|
||||
options = realloc(options, optlen + 2 + strlen(var) + 2);
|
||||
|
||||
fmt = "%.*s%s ";
|
||||
|
||||
var = strchrnul(var, '=');
|
||||
|
||||
if (quote_space)
|
||||
{
|
||||
if (*val)
|
||||
{
|
||||
val++;
|
||||
if (strchr(val, ' '))
|
||||
fmt = "%.*s\"%s\" ";
|
||||
}
|
||||
}
|
||||
|
||||
optlen += sprintf(options + optlen, fmt, (int)(val - var), var, val);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void *mmap_read(int fd, size_t size)
|
||||
{
|
||||
return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
}
|
||||
|
||||
static void *try_to_map_module(const char *filename, size_t *image_size_p)
|
||||
{
|
||||
void *image = NULL;
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
fprintf(stderr, "open %s failed:%s\n", filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fstat(fd, &st);
|
||||
|
||||
if (st.st_size <= *image_size_p)
|
||||
{
|
||||
size_t image_size = st.st_size;
|
||||
image = mmap_read(fd, image_size);
|
||||
|
||||
if (image == MAP_FAILED)
|
||||
{
|
||||
image = NULL;
|
||||
}
|
||||
else if (*(u_int32_t *)image != SWAP_BE32(0x7f454C46))
|
||||
{
|
||||
munmap(image, image_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
*image_size_p = image_size;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return image;
|
||||
}
|
||||
|
||||
static void *malloc_open_zipped_read_close(const char *filename, size_t *image_size_p)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_insmod(const char *modname, const char **argv)
|
||||
{
|
||||
int mmaped = 0;
|
||||
size_t image_size = INT_MAX - 4095;
|
||||
void *image = NULL;
|
||||
int ret;
|
||||
|
||||
if (!modname)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *options = *argv == NULL ? "" : parse_cmdline_module_options(argv, 0);
|
||||
|
||||
image = try_to_map_module(modname, &image_size);
|
||||
|
||||
if (image)
|
||||
{
|
||||
mmaped = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = ENOMEM;
|
||||
image = malloc_open_zipped_read_close(modname, &image_size);
|
||||
if (!image)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
init_module(image, image_size, options);
|
||||
|
||||
ret = errno;
|
||||
|
||||
if (mmaped)
|
||||
munmap(image, image_size);
|
||||
else
|
||||
free(image);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
fprintf(stderr, "insmod failed:%s\n", strerror(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
10
package/system/rdloader/src/insmod.h
Normal file
10
package/system/rdloader/src/insmod.h
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by juno on 2022/1/7.
|
||||
//
|
||||
|
||||
#ifndef INIT_INSMOD_H
|
||||
#define INIT_INSMOD_H
|
||||
|
||||
int do_insmod(const char *modname, const char **argv);
|
||||
|
||||
#endif //INIT_INSMOD_H
|
257
package/system/rdloader/src/main.c
Normal file
257
package/system/rdloader/src/main.c
Normal file
@ -0,0 +1,257 @@
|
||||
#include <sys/mount.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "insmod.h"
|
||||
#include "mknod.h"
|
||||
#include "mkdev_node.h"
|
||||
#include "cmdline.h"
|
||||
#include "switch_root.h"
|
||||
|
||||
static void hang(void);
|
||||
|
||||
static int mount_fs(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
unsigned long flags = MS_NOEXEC | MS_NOSUID | MS_RELATIME | MS_NODEV;
|
||||
|
||||
ret = mount(NULL, "/proc", "proc", flags, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = mount(NULL, "/sys", "sysfs", flags, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = mount(NULL, "/dev", "tmpfs", MS_RELATIME, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
ret = errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct dev_node_t
|
||||
{
|
||||
const char *mode;
|
||||
const char *name;
|
||||
char type;
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
} dev_nodes[] = {
|
||||
{
|
||||
.mode = "0666",
|
||||
.name = "/dev/tty",
|
||||
.type = 'c',
|
||||
.major = 5,
|
||||
.minor = 0,
|
||||
},
|
||||
{
|
||||
.mode = "0622",
|
||||
.name = "/dev/console",
|
||||
.type = 'c',
|
||||
.major = 5,
|
||||
.minor = 1,
|
||||
},
|
||||
{
|
||||
.mode = "0666",
|
||||
.name = "/dev/null",
|
||||
.type = 'c',
|
||||
.major = 1,
|
||||
.minor = 3,
|
||||
},
|
||||
{
|
||||
.mode = "0666",
|
||||
.name = "/dev/zero",
|
||||
.type = 'c',
|
||||
.major = 1,
|
||||
.minor = 5,
|
||||
},
|
||||
};
|
||||
|
||||
static int make_node(void)
|
||||
{
|
||||
for (int i = 0; i < sizeof(dev_nodes) / sizeof((dev_nodes)[0]); i++)
|
||||
{
|
||||
if (do_mknod(dev_nodes[i].mode, dev_nodes[i].name, dev_nodes[i].type, dev_nodes[i].major, dev_nodes[i].minor) < 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "make %s failed:%s\n", dev_nodes[i].name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int insert_kernel_module(const char *path, const char **argv)
|
||||
{
|
||||
int ret;
|
||||
FILE *fp = NULL;
|
||||
char module_name[1024] = {0};
|
||||
|
||||
if (access(path, F_OK) != 0)
|
||||
{
|
||||
fprintf(stderr, "%s not found\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp)
|
||||
{
|
||||
fprintf(stderr, "open %s failed:%s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((fgets(module_name, sizeof(module_name) - 1, fp)) != NULL)
|
||||
{
|
||||
for (int i = 0; i < sizeof(module_name); i++)
|
||||
{
|
||||
if (module_name[i] == '\n')
|
||||
{
|
||||
module_name[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = do_insmod(module_name, argv);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void e2fsck(const char *dev_path)
|
||||
{
|
||||
int pid;
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
printf("fork failed");
|
||||
hang();
|
||||
}
|
||||
if (pid == 0)
|
||||
{
|
||||
execl("/bin/e2fsck", "-f", "-y", dev_path);
|
||||
printf("execl failed");
|
||||
hang();
|
||||
}
|
||||
else
|
||||
{
|
||||
waitpid(pid);
|
||||
}
|
||||
}
|
||||
|
||||
static int mount_rootfs(struct bootargs_t *bootargs)
|
||||
{
|
||||
int ret = 0;
|
||||
char realroot[PATH_MAX];
|
||||
struct fstype *fstype = NULL;
|
||||
|
||||
// OpenWrt dont have /dev/disk/by-* yet, use realpath as workaround.
|
||||
if (realpath(bootargs->root, realroot) == NULL)
|
||||
return -1;
|
||||
|
||||
fstype = bootargs->fstype;
|
||||
|
||||
for (struct fstype *next = fstype->next; fstype; next = fstype->next, fstype = next)
|
||||
{
|
||||
if (strcmp(fstype->name, "ext4") == 0)
|
||||
{
|
||||
e2fsck(realroot);
|
||||
}
|
||||
ret = mount(realroot, "/root", fstype->name, MS_RELATIME, NULL);
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hang()
|
||||
{
|
||||
exit(-1);
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
int ret;
|
||||
struct bootargs_t *bootargs = NULL;
|
||||
|
||||
if (getpid() != 1)
|
||||
{
|
||||
fprintf(stderr, "must run PID 1\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
if ((ret = mount_fs()) < 0)
|
||||
{
|
||||
fprintf(stderr, "mount ramdisk fs failed:%s\n", strerror(ret));
|
||||
hang();
|
||||
}
|
||||
|
||||
if (make_node() < 0)
|
||||
{
|
||||
fprintf(stderr, "make ramdisk dev node failed\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
if ((ret = parse_cmdline(&bootargs)) < 0)
|
||||
{
|
||||
fprintf(stderr, "cmdline format error\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
if (insert_kernel_module("/etc/rdloader_list", argv + 1) != 0)
|
||||
{
|
||||
fprintf(stderr, "failed to load kmods\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
printf("Waiting for root: %s\n", bootargs->root);
|
||||
|
||||
do
|
||||
{
|
||||
ret = mkdev_node();
|
||||
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
ret = mount_rootfs(bootargs);
|
||||
} while (ret != 0);
|
||||
|
||||
free_bootargs(&bootargs);
|
||||
|
||||
umount("/dev");
|
||||
umount("/proc");
|
||||
umount("/sys");
|
||||
|
||||
switch_root("/root", "/etc/preinit", argv++);
|
||||
|
||||
return 0;
|
||||
}
|
272
package/system/rdloader/src/mkdev_node.c
Normal file
272
package/system/rdloader/src/mkdev_node.c
Normal file
@ -0,0 +1,272 @@
|
||||
//
|
||||
// Created by juno on 2022/1/10.
|
||||
//
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <blkid/blkid.h>
|
||||
|
||||
#include "mkdev_node.h"
|
||||
#include "mknod.h"
|
||||
#include "blkid2.h"
|
||||
|
||||
static int parse_devno(const char *devname, int *maj, int *min)
|
||||
{
|
||||
FILE *fp;
|
||||
char *major_s, *minor_s;
|
||||
int major, minor;
|
||||
char dev_path[1024] = {0};
|
||||
char dev_no[32] = {0};
|
||||
|
||||
snprintf(dev_path, sizeof(dev_path) - 1, "/sys/class/block/%s/dev", devname);
|
||||
|
||||
fp = fopen(dev_path, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
|
||||
if (!fgets(dev_no, 31, fp))
|
||||
return -1;
|
||||
|
||||
fclose(fp);
|
||||
major_s = strtok(dev_no, ":");
|
||||
minor_s = strtok(NULL, ":");
|
||||
|
||||
major = (int)strtoul(major_s, NULL, 0);
|
||||
|
||||
minor = (int)strtoul(minor_s, NULL, 0);
|
||||
|
||||
*maj = major;
|
||||
*min = minor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mkpartion_node(const char *devname)
|
||||
{
|
||||
int ret = 0;
|
||||
dev_t part_devno;
|
||||
dev_t disk_devno;
|
||||
char *disk_name;
|
||||
blkid_probe disk_pr;
|
||||
blkid_partlist ls;
|
||||
blkid_partition par;
|
||||
const char *uuid;
|
||||
char *dev_path = NULL;
|
||||
|
||||
asprintf(&dev_path, "/dev/%s", devname);
|
||||
|
||||
if (dev_path == NULL)
|
||||
return -1;
|
||||
|
||||
blkid_probe part_pr = blkid_new_probe_from_filename(dev_path);
|
||||
|
||||
if (!part_pr)
|
||||
{
|
||||
ret = -1;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
part_devno = blkid_probe_get_devno(part_pr);
|
||||
|
||||
if (!part_devno)
|
||||
{
|
||||
ret = -1;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
disk_devno = blkid_probe_get_wholedisk_devno(part_pr);
|
||||
|
||||
if (!disk_devno)
|
||||
{
|
||||
ret = -1;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
disk_name = blkid_devno_to_devname(disk_devno);
|
||||
|
||||
if (!disk_name)
|
||||
{
|
||||
ret = -1;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
disk_pr = blkid_new_probe_from_filename(disk_name);
|
||||
|
||||
if (!disk_pr)
|
||||
{
|
||||
ret = -1;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ls = blkid_probe_get_partitions(disk_pr);
|
||||
|
||||
if (!ls)
|
||||
{
|
||||
ret = -1;
|
||||
goto out4;
|
||||
}
|
||||
|
||||
par = blkid_partlist_devno_to_partition(ls, part_devno);
|
||||
|
||||
uuid = blkid_partition_get_uuid(par);
|
||||
|
||||
if (uuid)
|
||||
{
|
||||
char long_path[1024] = {0};
|
||||
snprintf(long_path, sizeof(long_path) - 1, "/dev/disk/by-partuuid/%s", uuid);
|
||||
|
||||
if (access(long_path, F_OK) == 0)
|
||||
goto out4;
|
||||
|
||||
if (access(dev_path, F_OK) != 0)
|
||||
goto out4;
|
||||
|
||||
symlink(dev_path, long_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
out4:
|
||||
blkid_free_probe(disk_pr);
|
||||
out3:
|
||||
free(disk_name);
|
||||
out2:
|
||||
blkid_free_probe(part_pr);
|
||||
out1:
|
||||
free(dev_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dev_by_partuuit(void)
|
||||
{
|
||||
DIR *dir;
|
||||
DIR *disk_dir;
|
||||
struct dirent *filename;
|
||||
struct dirent *partname;
|
||||
char *disk = NULL;
|
||||
|
||||
mkdir("/dev/disk/by-partuuid", 0755);
|
||||
|
||||
dir = opendir("/sys/block");
|
||||
|
||||
if (!dir)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((filename = readdir(dir)))
|
||||
{
|
||||
if (filename->d_type != DT_LNK)
|
||||
continue;
|
||||
|
||||
asprintf(&disk, "/sys/block/%s", filename->d_name);
|
||||
|
||||
disk_dir = opendir(disk);
|
||||
|
||||
if (disk)
|
||||
free(disk);
|
||||
|
||||
if (disk_dir)
|
||||
{
|
||||
while ((partname = readdir(disk_dir)))
|
||||
{
|
||||
char *dev = NULL;
|
||||
asprintf(&dev, "/sys/block/%s/%s/dev", filename->d_name, partname->d_name);
|
||||
|
||||
if (access(dev, F_OK) == 0)
|
||||
{
|
||||
mkpartion_node(partname->d_name);
|
||||
}
|
||||
|
||||
if (dev)
|
||||
free(dev);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(disk_dir);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdev_node(void)
|
||||
{
|
||||
int ret;
|
||||
struct dirent *filename;
|
||||
DIR *dir = NULL;
|
||||
char dev_path[1024];
|
||||
char uuid_node[1024];
|
||||
|
||||
dir = opendir("/sys/class/block");
|
||||
|
||||
ret = mkdir("/dev/disk", 0755);
|
||||
|
||||
if (ret < 0 && errno != EEXIST)
|
||||
{
|
||||
fprintf(stderr, "create /dev/disk directory failed:%s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mkdir("/dev/disk/by-uuid", 0755);
|
||||
|
||||
if (ret < 0 && errno != EEXIST)
|
||||
{
|
||||
fprintf(stderr, "create /dev/disk/by-uuid directory failed:%s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((filename = readdir(dir)))
|
||||
{
|
||||
if (filename->d_type == DT_LNK)
|
||||
{
|
||||
int major, minor;
|
||||
char *uuid = NULL;
|
||||
|
||||
memset(dev_path, 0, sizeof(dev_path));
|
||||
|
||||
snprintf(dev_path, sizeof(dev_path) - 1, "/dev/%s", filename->d_name);
|
||||
|
||||
if (access(dev_path, F_OK) == 0)
|
||||
continue;
|
||||
|
||||
if (parse_devno(filename->d_name, &major, &minor) < 0)
|
||||
continue;
|
||||
|
||||
ret = do_mknod("0755", dev_path, 'b', major, minor);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = get_blkid(dev_path, &uuid);
|
||||
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
memset(uuid_node, 0, sizeof(uuid_node));
|
||||
snprintf(uuid_node, sizeof(uuid_node) - 1, "/dev/disk/by-uuid/%s", uuid);
|
||||
|
||||
symlink(dev_path, uuid_node);
|
||||
if (uuid)
|
||||
{
|
||||
free(uuid);
|
||||
uuid = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
dev_by_partuuit();
|
||||
|
||||
return 0;
|
||||
}
|
10
package/system/rdloader/src/mkdev_node.h
Normal file
10
package/system/rdloader/src/mkdev_node.h
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by juno on 2022/1/10.
|
||||
//
|
||||
|
||||
#ifndef INIT_MKDEV_NODE_H
|
||||
#define INIT_MKDEV_NODE_H
|
||||
|
||||
int mkdev_node(void);
|
||||
|
||||
#endif //INIT_MKDEV_NODE_H
|
217
package/system/rdloader/src/mknod.c
Normal file
217
package/system/rdloader/src/mknod.c
Normal file
@ -0,0 +1,217 @@
|
||||
//
|
||||
// Created by juno on 2022/1/7.
|
||||
//
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "mknod.h"
|
||||
|
||||
static const mode_t modes_cubp[] = {
|
||||
S_IFIFO,
|
||||
S_IFCHR,
|
||||
S_IFBLK,
|
||||
S_IFLNK,
|
||||
};
|
||||
|
||||
#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
|
||||
static mode_t parse_mode(const char *s)
|
||||
{
|
||||
static const mode_t who_mask[] = {
|
||||
S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
|
||||
S_ISUID | S_IRWXU, /* u */
|
||||
S_ISGID | S_IRWXG, /* g */
|
||||
S_IRWXO /* o */
|
||||
};
|
||||
static const mode_t perm_mask[] = {
|
||||
S_IRUSR | S_IRGRP | S_IROTH, /* r */
|
||||
S_IWUSR | S_IWGRP | S_IWOTH, /* w */
|
||||
S_IXUSR | S_IXGRP | S_IXOTH, /* x */
|
||||
S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */
|
||||
S_ISUID | S_ISGID, /* s */
|
||||
S_ISVTX /* t */
|
||||
};
|
||||
static const char who_chars[] ALIGN1 = "augo";
|
||||
static const char perm_chars[] ALIGN1 = "rwxXst";
|
||||
|
||||
const char *p;
|
||||
mode_t wholist;
|
||||
mode_t permlist;
|
||||
mode_t new_mode;
|
||||
char op;
|
||||
|
||||
if ((unsigned char)(*s - '0') < 8)
|
||||
{
|
||||
unsigned long tmp;
|
||||
char *e;
|
||||
|
||||
tmp = strtoul(s, &e, 8);
|
||||
if (*e || (tmp > 07777U))
|
||||
{ /* Check range and trailing chars. */
|
||||
return -1;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
new_mode = 0666;
|
||||
|
||||
/* Note: we allow empty clauses, and hence empty modes.
|
||||
* We treat an empty mode as no change to perms. */
|
||||
|
||||
while (*s)
|
||||
{ /* Process clauses. */
|
||||
if (*s == ',')
|
||||
{ /* We allow empty clauses. */
|
||||
++s;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get a wholist. */
|
||||
wholist = 0;
|
||||
WHO_LIST:
|
||||
p = who_chars;
|
||||
do
|
||||
{
|
||||
if (*p == *s)
|
||||
{
|
||||
wholist |= who_mask[(int)(p - who_chars)];
|
||||
if (!*++s)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
goto WHO_LIST;
|
||||
}
|
||||
} while (*++p);
|
||||
|
||||
do
|
||||
{ /* Process action list. */
|
||||
if ((*s != '+') && (*s != '-'))
|
||||
{
|
||||
if (*s != '=')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
/* Since op is '=', clear all bits corresponding to the
|
||||
* wholist, or all file bits if wholist is empty. */
|
||||
permlist = ~FILEMODEBITS;
|
||||
if (wholist)
|
||||
{
|
||||
permlist = ~wholist;
|
||||
}
|
||||
new_mode &= permlist;
|
||||
}
|
||||
op = *s++;
|
||||
|
||||
/* Check for permcopy. */
|
||||
p = who_chars + 1; /* Skip 'a' entry. */
|
||||
do
|
||||
{
|
||||
if (*p == *s)
|
||||
{
|
||||
int i = 0;
|
||||
permlist = who_mask[(int)(p - who_chars)] & (S_IRWXU | S_IRWXG | S_IRWXO) & new_mode;
|
||||
do
|
||||
{
|
||||
if (permlist & perm_mask[i])
|
||||
{
|
||||
permlist |= perm_mask[i];
|
||||
}
|
||||
} while (++i < 3);
|
||||
++s;
|
||||
goto GOT_ACTION;
|
||||
}
|
||||
} while (*++p);
|
||||
|
||||
/* It was not a permcopy, so get a permlist. */
|
||||
permlist = 0;
|
||||
PERM_LIST:
|
||||
p = perm_chars;
|
||||
do
|
||||
{
|
||||
if (*p == *s)
|
||||
{
|
||||
if ((*p != 'X') || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH)))
|
||||
{
|
||||
permlist |= perm_mask[(int)(p - perm_chars)];
|
||||
}
|
||||
if (!*++s)
|
||||
{
|
||||
break;
|
||||
}
|
||||
goto PERM_LIST;
|
||||
}
|
||||
} while (*++p);
|
||||
GOT_ACTION:
|
||||
if (permlist)
|
||||
{ /* The permlist was nonempty. */
|
||||
mode_t tmp = wholist;
|
||||
if (!wholist)
|
||||
{
|
||||
mode_t u_mask = umask(0);
|
||||
umask(u_mask);
|
||||
tmp = ~u_mask;
|
||||
}
|
||||
permlist &= tmp;
|
||||
if (op == '-')
|
||||
{
|
||||
new_mode &= ~permlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_mode |= permlist;
|
||||
}
|
||||
}
|
||||
} while (*s && (*s != ','));
|
||||
}
|
||||
|
||||
return new_mode;
|
||||
}
|
||||
|
||||
static mode_t char_to_mode(char type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 'f':
|
||||
return modes_cubp[0];
|
||||
case 'c':
|
||||
return modes_cubp[1];
|
||||
case 'b':
|
||||
return modes_cubp[2];
|
||||
case 'l':
|
||||
return modes_cubp[3];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int do_mknod(const char *mod, const char *name, char type, int maj, int min)
|
||||
{
|
||||
int ret;
|
||||
mode_t mode;
|
||||
dev_t dev;
|
||||
|
||||
mode = parse_mode(mod);
|
||||
if (mode != (mode_t)-1)
|
||||
umask(0);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "mode failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = makedev(maj, min);
|
||||
|
||||
mode |= char_to_mode(type);
|
||||
|
||||
ret = mknod(name, mode, dev);
|
||||
|
||||
if (ret < 0)
|
||||
ret = errno;
|
||||
|
||||
return ret;
|
||||
}
|
11
package/system/rdloader/src/mknod.h
Normal file
11
package/system/rdloader/src/mknod.h
Normal file
@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by juno on 2022/1/7.
|
||||
//
|
||||
|
||||
#ifndef INIT_MKNOD_H
|
||||
#define INIT_MKNOD_H
|
||||
|
||||
#define ALIGN1 __attribute__((aligned(1)))
|
||||
int do_mknod(const char *mod, const char *name, char type, int maj, int min);
|
||||
|
||||
#endif //INIT_MKNOD_H
|
108
package/system/rdloader/src/switch_root.c
Normal file
108
package/system/rdloader/src/switch_root.c
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// Created by juno on 2022/1/12.
|
||||
//
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/mount.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "switch_root.h"
|
||||
|
||||
static char *last_char_is(const char *s, int c)
|
||||
{
|
||||
if (!s[0])
|
||||
return NULL;
|
||||
while (s[1])
|
||||
s++;
|
||||
|
||||
return (*s == (char)c) ? (char *)s : NULL;
|
||||
}
|
||||
|
||||
static char *concat_path_file(const char *path, const char *filename)
|
||||
{
|
||||
char *lc;
|
||||
char *ret;
|
||||
|
||||
if (!path)
|
||||
path = "";
|
||||
|
||||
lc = last_char_is(path, '/');
|
||||
|
||||
while (*filename == '/')
|
||||
filename++;
|
||||
|
||||
asprintf(&ret, "%s/%s/%s", path, (lc == NULL ? "/" : ""), filename);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void delete_contents(const char *directory, dev_t rootdev)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
struct stat st;
|
||||
|
||||
if (lstat(directory, &st) || st.st_dev != rootdev)
|
||||
return;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
dir = opendir(directory);
|
||||
if (dir)
|
||||
{
|
||||
while ((d = readdir(dir)))
|
||||
{
|
||||
char *newdir = d->d_name;
|
||||
|
||||
if (DOT_OR_DOTDOT(newdir))
|
||||
continue;
|
||||
|
||||
newdir = concat_path_file(directory, newdir);
|
||||
delete_contents(newdir, rootdev);
|
||||
free(newdir);
|
||||
}
|
||||
closedir(dir);
|
||||
rmdir(directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink(directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void switch_root(const char *new_root, const char *prog, char *const argv[])
|
||||
{
|
||||
struct stat st;
|
||||
dev_t root_dev;
|
||||
|
||||
chdir(new_root);
|
||||
stat("/", &st);
|
||||
|
||||
root_dev = st.st_dev;
|
||||
|
||||
stat(".", &st);
|
||||
|
||||
if (st.st_dev == root_dev)
|
||||
{
|
||||
fprintf(stderr, "%s must be a mountpoint\n", new_root);
|
||||
return;
|
||||
}
|
||||
|
||||
delete_contents("/", root_dev);
|
||||
if (mount(".", "/", NULL, MS_MOVE, NULL))
|
||||
{
|
||||
fprintf(stderr, "failed to moving root\n");
|
||||
return;
|
||||
}
|
||||
|
||||
chroot(".");
|
||||
|
||||
execv(prog, argv);
|
||||
}
|
12
package/system/rdloader/src/switch_root.h
Normal file
12
package/system/rdloader/src/switch_root.h
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by juno on 2022/1/12.
|
||||
//
|
||||
|
||||
#ifndef INIT_SWITCH_ROOT_H
|
||||
#define INIT_SWITCH_ROOT_H
|
||||
|
||||
#define DOT_OR_DOTDOT(s) ((s)[0] == '.' && (!(s)[1] || ((s)[1] == '.' && !(s)[2])))
|
||||
void switch_root(const char *newroot, const char *prog, char *const argv[]);
|
||||
|
||||
|
||||
#endif //INIT_SWITCH_ROOT_H
|
13
scripts/gen-rddependencies.sh
Executable file
13
scripts/gen-rddependencies.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
TARGETS=$*
|
||||
READELF="${READELF:-readelf}"
|
||||
XARGS="${XARGS:-xargs -r}"
|
||||
|
||||
find $TARGETS -type f -a -exec file {} \; | \
|
||||
sed -n -e 's/^\(.*\):.*ELF.*\(executable\|shared object\).*,.*/\1/p' | \
|
||||
$XARGS -n1 $READELF -l | grep 'Requesting' | cut -d':' -f2 | tr -d ' ]' | \
|
||||
$XARGS basename
|
||||
|
||||
cd `dirname ${0}`
|
||||
./gen-dependencies.sh ${TARGETS}
|
278
target/linux/ramips/dts/mt7621_hatlab_gateboard-one.dts
Normal file
278
target/linux/ramips/dts/mt7621_hatlab_gateboard-one.dts
Normal file
@ -0,0 +1,278 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "mt7621.dtsi"
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/thermal/thermal.h>
|
||||
|
||||
/ {
|
||||
compatible = "hatlab,gateboard-one", "mediatek,mt7621-soc";
|
||||
model = "HATLab GateBoard-One";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_sys: sys {
|
||||
label = "green:sys";
|
||||
gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
usb {
|
||||
label = "blue:usb";
|
||||
gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
|
||||
trigger-sources = <&xhci_ehci_port1>;
|
||||
linux,default-trigger = "usbport";
|
||||
};
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_export {
|
||||
compatible = "gpio-export";
|
||||
#size-cells = <0>;
|
||||
|
||||
power_peripheral {
|
||||
gpio-export,name = "power_peripheral";
|
||||
gpio-export,output = <0>;
|
||||
gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_fan: cpu_fan {
|
||||
compatible = "gpio-fan";
|
||||
gpios = <&gpio 13 GPIO_ACTIVE_HIGH
|
||||
&gpio 14 GPIO_ACTIVE_HIGH>;
|
||||
gpio-fan,speed-map = < 0 0
|
||||
2000 1
|
||||
4000 2
|
||||
6000 3>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu-thermal {
|
||||
polling-delay = <1000>;
|
||||
polling-delay-passive = <250>;
|
||||
|
||||
thermal-sensors = <&cpu_sensor>;
|
||||
|
||||
trips {
|
||||
cpu_warm: cpu-warm {
|
||||
temperature = <26000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
|
||||
cpu_hot: cpu-hot {
|
||||
temperature = <37000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_alert: cpu-alert {
|
||||
temperature = <75000>;
|
||||
hysteresis = <2000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
cpu_crit: cpu-crit {
|
||||
temperature = <80000>;
|
||||
hysteresis = <2000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&cpu_warm>;
|
||||
cooling-device = <&cpu_fan THERMAL_NO_LIMIT 2>;
|
||||
};
|
||||
|
||||
map1 {
|
||||
trip = <&cpu_hot>;
|
||||
cooling-device = <&cpu_fan 3 THERMAL_NO_LIMIT>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c_sfp: i2c-sfp {
|
||||
compatible = "i2c-gpio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sda-gpios = <&expender0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&expender0 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
sfp: sfp {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c_sfp>;
|
||||
maximum-power-milliwatt = <5000>;
|
||||
mod-def0-gpios = <&expender0 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
spi-nor@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
|
||||
partitions@0 {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@40000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x40000 0x10000>;
|
||||
};
|
||||
|
||||
factory: partition@50000 {
|
||||
label = "factory";
|
||||
reg = <0x50000 0x10000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c {
|
||||
status = "okay";
|
||||
|
||||
expender0: pcf8574a@38 {
|
||||
compatible = "nxp,pcf8574a";
|
||||
reg = <0x38>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
cpu_sensor: lm75@4f {
|
||||
compatible = "national,lm75";
|
||||
reg = <0x4f>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
rtc@51 {
|
||||
compatible = "nxp,pcf8563";
|
||||
reg = <0x51>;
|
||||
};
|
||||
};
|
||||
|
||||
&mdio {
|
||||
ephy7: ethernet-phy@7 {
|
||||
reg = <7>;
|
||||
eee-broken-1000t;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
label = "dsa";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
status = "okay";
|
||||
label = "eth5";
|
||||
phy-handle = <&ephy7>;
|
||||
phy-mode = "rgmii-rxid";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <6>;
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
port@0 {
|
||||
status = "okay";
|
||||
label = "eth0";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <1>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
status = "okay";
|
||||
label = "eth1";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <2>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
status = "okay";
|
||||
label = "eth2";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <3>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
status = "okay";
|
||||
label = "eth3";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <4>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
status = "okay";
|
||||
label = "eth4";
|
||||
mtd-mac-address = <&factory 0x0>;
|
||||
mtd-mac-address-increment = <5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pcie {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdhci {
|
||||
status = "okay";
|
||||
max-frequency = <20000000>;
|
||||
};
|
||||
|
||||
&state_default {
|
||||
gpio {
|
||||
groups = "wdt", "jtag";
|
||||
function = "gpio";
|
||||
};
|
||||
};
|
||||
|
||||
&uartlite2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uartlite3 {
|
||||
status = "okay";
|
||||
};
|
@ -99,6 +99,7 @@
|
||||
#define MAX_SGMT_SZ (MAX_DMA_CNT)
|
||||
#define MAX_REQ_SZ (MAX_SGMT_SZ * 8)
|
||||
|
||||
static int host_max_mclk = HOST_MAX_MCLK;
|
||||
static int cd_active_low = 1;
|
||||
|
||||
//=================================
|
||||
@ -455,7 +456,7 @@ static void msdc_tasklet_card(struct work_struct *work)
|
||||
host->card_inserted = inserted;
|
||||
|
||||
if (!host->suspend) {
|
||||
host->mmc->f_max = HOST_MAX_MCLK;
|
||||
host->mmc->f_max = host_max_mclk;
|
||||
mmc_detect_change(host->mmc, msecs_to_jiffies(20));
|
||||
}
|
||||
|
||||
@ -2233,10 +2234,13 @@ static int msdc_drv_probe(struct platform_device *pdev)
|
||||
goto host_free;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "max-frequency", &ret) == 0)
|
||||
host_max_mclk = ret;
|
||||
|
||||
/* Set host parameters to mmc */
|
||||
mmc->ops = &mt_msdc_ops;
|
||||
mmc->f_min = HOST_MIN_MCLK;
|
||||
mmc->f_max = HOST_MAX_MCLK;
|
||||
mmc->f_max = host_max_mclk;
|
||||
mmc->ocr_avail = MSDC_OCR_AVAIL;
|
||||
|
||||
mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
|
||||
|
@ -26,6 +26,71 @@ define Build/gemtek-trailer
|
||||
printf "%s%08X" ".GEMTEK." "$$(cksum $@ | cut -d ' ' -f1)" >> $@
|
||||
endef
|
||||
|
||||
define Build/hatlab-gateboard-combined
|
||||
rm -fR $@.bootfs.img
|
||||
|
||||
mkfs.fat $@.bootfs.img -C 16384
|
||||
mcopy -i $@.bootfs.img $(IMAGE_KERNEL) ::vmlinux.itb
|
||||
|
||||
( \
|
||||
set $$(ptgen -o $@ -h 4 -s 63 -l 1024 -g -p 16M -p "${CONFIG_TARGET_ROOTFS_PARTSIZE}M" -G ${IMG_PART_DISKGUID}); \
|
||||
BOOTFSOFFSET="$$(($$1 / 512))"; \
|
||||
ROOTFSOFFSET="$$(($$3 / 512))"; \
|
||||
dd if="$@.bootfs.img" of="$@" bs=512 seek="$${BOOTFSOFFSET}" conv=notrunc; \
|
||||
dd if="${IMAGE_ROOTFS}" of="$@" bs=512 seek="$${ROOTFSOFFSET}" conv=notrunc; \
|
||||
)
|
||||
endef
|
||||
|
||||
define Build/hatlab-gateboard-kernel
|
||||
rm -fR $@.initrd
|
||||
rm -fR $@.initrd.cpio
|
||||
|
||||
mkdir -p $@.initrd/{bin,dev,proc,sys,lib,etc}
|
||||
mkdir -p $@.initrd/lib/modules/$(LINUX_VERSION)
|
||||
|
||||
$(CP) $(STAGING_DIR)/rdloader/bin/* $@.initrd/bin/
|
||||
$(CP) $(STAGING_DIR)/rdloader/lib/* $@.initrd/lib/
|
||||
$(CP) $(STAGING_DIR)/rdloader/etc/* $@.initrd/etc/
|
||||
|
||||
$(RSTRIP) $@.initrd/bin/
|
||||
$(RSTRIP) $@.initrd/lib/
|
||||
|
||||
chmod +x $@.initrd/bin/*
|
||||
ln -s ./bin/rdloader $@.initrd/init
|
||||
|
||||
( \
|
||||
KMODS=(usb-common nls_base usbcore xhci-hcd xhci-mtk jbd2 mbcache ext4 scsi_mod usb-storage sd_mod mmc_core mmc_block mtk_sd crc32c_generic); \
|
||||
for kmod in "$${KMODS[@]}"; do \
|
||||
$(CP) \
|
||||
$(TARGET_DIR)/lib/modules/$(LINUX_VERSION)/$$kmod.ko \
|
||||
$@.initrd/lib/modules/$(LINUX_VERSION)/; \
|
||||
echo /lib/modules/$(LINUX_VERSION)/$$kmod.ko \
|
||||
>> $@.initrd/etc/rdloader_list; \
|
||||
done; \
|
||||
)
|
||||
|
||||
( \
|
||||
if [ -f $(STAGING_DIR_HOST)/bin/cpio ]; then \
|
||||
CPIO=$(STAGING_DIR_HOST)/bin/cpio; \
|
||||
else \
|
||||
CPIO="cpio"; \
|
||||
fi; \
|
||||
cd $@.initrd; \
|
||||
find . | cpio -o -H newc -R 0:0 > $@.initrd.cpio; \
|
||||
)
|
||||
|
||||
$(TOPDIR)/scripts/mkits.sh \
|
||||
-D $(DEVICE_NAME) -o $@.its -k $@ \
|
||||
-C gzip -d $(KDIR)/image-$(DEVICE_DTS).dtb \
|
||||
-i $@.initrd.cpio \
|
||||
-a $(KERNEL_LOADADDR) -e $(KERNEL_LOADADDR) \
|
||||
-c config-1 -A $(LINUX_KARCH) -v $(LINUX_VERSION)
|
||||
|
||||
PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new
|
||||
|
||||
@mv $@.new $@
|
||||
endef
|
||||
|
||||
define Build/iodata-factory
|
||||
$(eval fw_size=$(word 1,$(1)))
|
||||
$(eval fw_type=$(word 2,$(1)))
|
||||
@ -672,6 +737,28 @@ define Device/gnubee_gb-pc2
|
||||
endef
|
||||
TARGET_DEVICES += gnubee_gb-pc2
|
||||
|
||||
define Device/hatlab_gateboard-one
|
||||
$(Device/dsa-migration)
|
||||
DEVICE_VENDOR := HATLab
|
||||
DEVICE_MODEL := GateBoard-One
|
||||
DEVICE_PACKAGES := kmod-fs-ext4 kmod-gpio-pcf857x kmod-hwmon-gpiofan \
|
||||
kmod-hwmon-lm75 kmod-i2c-gpio kmod-rtc-pcf8563 kmod-sdhci-mt7620 \
|
||||
kmod-sfp kmod-thermal kmod-usb3 kmod-usb-ledtrig-usbport rdloader
|
||||
KERNEL := kernel-bin | gzip | hatlab-gateboard-kernel
|
||||
IMAGE/kernel.itb := append-kernel
|
||||
IMAGE/rootfs.img := append-rootfs | pad-to $(ROOTFS_PARTSIZE)
|
||||
IMAGE/rootfs.img.gz := append-rootfs | pad-to $(ROOTFS_PARTSIZE) | gzip
|
||||
IMAGE/combined.img := hatlab-gateboard-combined | append-metadata
|
||||
IMAGE/combined.img.gz := hatlab-gateboard-combined | gzip | append-metadata
|
||||
IMAGES := kernel.itb
|
||||
ifeq ($(CONFIG_TARGET_IMAGES_GZIP),y)
|
||||
IMAGES += rootfs.img.gz combined.img.gz
|
||||
else
|
||||
IMAGES += rootfs.img combined.img
|
||||
endif
|
||||
endef
|
||||
TARGET_DEVICES += hatlab_gateboard-one
|
||||
|
||||
define Device/hilink_hlk-7621a
|
||||
IMAGE_SIZE := 32448k
|
||||
DEVICE_VENDOR := HiLink
|
||||
|
@ -57,6 +57,9 @@ ramips_setup_interfaces()
|
||||
gnubee,gb-pc2)
|
||||
ucidef_set_interface_lan "lan1 lan2"
|
||||
;;
|
||||
hatlab,gateboard-one)
|
||||
ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth4" "eth5"
|
||||
;;
|
||||
linksys,re6500|\
|
||||
netgear,wac104)
|
||||
ucidef_set_interface_lan "lan1 lan2 lan3 lan4"
|
||||
|
88
target/linux/ramips/mt7621/base-files/lib/upgrade/hatlab.sh
Normal file
88
target/linux/ramips/mt7621/base-files/lib/upgrade/hatlab.sh
Normal file
@ -0,0 +1,88 @@
|
||||
. /lib/functions.sh
|
||||
|
||||
hatlab_check_image() {
|
||||
local diskdev partdev diff
|
||||
|
||||
export_bootdevice && export_partdevice diskdev 0 || {
|
||||
echo "Unable to determine upgrade device"
|
||||
return 1
|
||||
}
|
||||
|
||||
get_partitions "/dev/$diskdev" bootdisk
|
||||
|
||||
#extract the boot sector from the image
|
||||
get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b 2>/dev/null
|
||||
|
||||
get_partitions /tmp/image.bs image
|
||||
|
||||
#compare tables
|
||||
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
|
||||
|
||||
rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image
|
||||
|
||||
if [ -n "$diff" ]; then
|
||||
echo "Partition layout has changed. Full image will be written."
|
||||
ask_bool 0 "Abort" && exit 1
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
hatlab_copy_config() {
|
||||
local partdev parttype=ext4
|
||||
|
||||
if export_partdevice partdev 2; then
|
||||
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
|
||||
cp -af "$UPGRADE_BACKUP" "/mnt/$BACKUP_FILE"
|
||||
umount /mnt
|
||||
fi
|
||||
}
|
||||
|
||||
hatlab_do_upgrade() {
|
||||
local diskdev partdev diff
|
||||
|
||||
export_bootdevice && export_partdevice diskdev 0 || {
|
||||
echo "Unable to determine upgrade device"
|
||||
return 1
|
||||
}
|
||||
|
||||
sync
|
||||
|
||||
if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
|
||||
get_partitions "/dev/$diskdev" bootdisk
|
||||
|
||||
#extract the boot sector from the image
|
||||
get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b
|
||||
|
||||
get_partitions /tmp/image.bs image
|
||||
|
||||
#compare tables
|
||||
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
|
||||
else
|
||||
diff=1
|
||||
fi
|
||||
|
||||
if [ -n "$diff" ]; then
|
||||
get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync
|
||||
|
||||
# Separate removal and addtion is necessary; otherwise, partition 1
|
||||
# will be missing if it overlaps with the old partition 2
|
||||
partx -d - "/dev/$diskdev"
|
||||
partx -a - "/dev/$diskdev"
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
#iterate over each partition from the image and write it to the boot disk
|
||||
while read part start size; do
|
||||
if export_partdevice partdev $part; then
|
||||
echo "Writing image to /dev/$partdev..."
|
||||
get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync
|
||||
else
|
||||
echo "Unable to find partition $part device, skipped."
|
||||
fi
|
||||
done < /tmp/partmap.image
|
||||
|
||||
#copy partition uuid
|
||||
echo "Writing new UUID to /dev/$diskdev..."
|
||||
get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
|
||||
}
|
@ -9,6 +9,28 @@ RAMFS_COPY_BIN='fw_printenv fw_setenv'
|
||||
RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
|
||||
|
||||
platform_check_image() {
|
||||
local board=$(board_name)
|
||||
|
||||
case "$board" in
|
||||
hatlab,gateboard-one)
|
||||
hatlab_check_image "$1"
|
||||
return $?;
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
platform_copy_config() {
|
||||
local board=$(board_name)
|
||||
|
||||
case "$board" in
|
||||
hatlab,gateboard-one)
|
||||
hatlab_copy_config
|
||||
return $?;
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -86,6 +108,9 @@ platform_do_upgrade() {
|
||||
xiaomi,redmi-router-ac2100)
|
||||
nand_do_upgrade "$1"
|
||||
;;
|
||||
hatlab,gateboard-one)
|
||||
hatlab_do_upgrade "$1"
|
||||
;;
|
||||
iodata,wn-ax1167gr2|\
|
||||
iodata,wn-ax2033gr|\
|
||||
iodata,wn-dx1167r)
|
||||
|
@ -9,6 +9,10 @@ YES=
|
||||
|
||||
board=$(board_name)
|
||||
case $board in
|
||||
hatlab,gateboard-one)
|
||||
partname=factory
|
||||
offset=$((0x0))
|
||||
;;
|
||||
mqmaker,witi)
|
||||
partname=factory
|
||||
offset=$((0xe000))
|
||||
|
@ -233,6 +233,7 @@ CONFIG_RALINK=y
|
||||
CONFIG_RATIONAL=y
|
||||
CONFIG_RCU_NEED_SEGCBLIST=y
|
||||
CONFIG_RCU_STALL_COMMON=y
|
||||
CONFIG_REALTEK_PHY=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_REGMAP_MMIO=y
|
||||
CONFIG_REGULATOR=y
|
||||
|
@ -229,6 +229,7 @@ CONFIG_RALINK=y
|
||||
CONFIG_RATIONAL=y
|
||||
CONFIG_RCU_NEED_SEGCBLIST=y
|
||||
CONFIG_RCU_STALL_COMMON=y
|
||||
CONFIG_REALTEK_PHY=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_REGMAP_I2C=y
|
||||
CONFIG_REGMAP_MMIO=y
|
||||
|
@ -0,0 +1,12 @@
|
||||
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||
@@ -2410,6 +2410,9 @@ static const struct flash_info spi_nor_ids[] = {
|
||||
{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
|
||||
{ "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
|
||||
|
||||
+ /* PUYA */
|
||||
+ { "p25d40h", INFO(0x856013, 0, 64 * 1024, 8, SECT_4K) },
|
||||
+
|
||||
/* Spansion/Cypress -- single (large) sector size only, at least
|
||||
* for the chips listed here (without boot sectors).
|
||||
*/
|
150
target/linux/ramips/patches-5.4/992-rtl8211x.patch
Normal file
150
target/linux/ramips/patches-5.4/992-rtl8211x.patch
Normal file
@ -0,0 +1,150 @@
|
||||
--- a/drivers/net/phy/realtek.c
|
||||
+++ b/drivers/net/phy/realtek.c
|
||||
@@ -7,6 +7,7 @@
|
||||
* Author: Johnson Leung <r58129@freescale.com>
|
||||
*
|
||||
* Copyright (c) 2004 Freescale Semiconductor, Inc.
|
||||
+ * Copyright (c) 2022 Aodzip <aodzip@gmail.com>
|
||||
*/
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/phy.h>
|
||||
@@ -28,6 +29,12 @@
|
||||
|
||||
#define RTL8211F_INSR 0x1d
|
||||
|
||||
+#define RTL8211x_FIBER_ESR 0x0F
|
||||
+#define RTL8211x_MODE_MASK 0xC000
|
||||
+
|
||||
+#define RTL8211x_MODE_COPPER 0
|
||||
+#define RTL8211x_MODE_FIBER 1
|
||||
+
|
||||
#define RTL8211F_TX_DELAY BIT(8)
|
||||
#define RTL8211E_TX_DELAY BIT(1)
|
||||
#define RTL8211E_RX_DELAY BIT(2)
|
||||
@@ -49,6 +56,10 @@
|
||||
|
||||
#define RTL_GENERIC_PHYID 0x001cc800
|
||||
|
||||
+struct rtl8211x_priv {
|
||||
+ int lastmode;
|
||||
+};
|
||||
+
|
||||
MODULE_DESCRIPTION("Realtek PHY driver");
|
||||
MODULE_AUTHOR("Johnson Leung");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -443,6 +454,88 @@ static int rtl8125_match_phy_device(struct phy_device *phydev)
|
||||
rtlgen_supports_2_5gbps(phydev);
|
||||
}
|
||||
|
||||
+static int rtl8211x_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct device *dev = &phydev->mdio.dev;
|
||||
+ struct rtl8211x_priv *priv;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(struct rtl8211x_priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ phydev->priv = priv;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void rtl8211x_remove(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct device *dev = &phydev->mdio.dev;
|
||||
+ struct rtl8211x_priv *priv = phydev->priv;
|
||||
+
|
||||
+ if (priv)
|
||||
+ devm_kfree(dev, priv);
|
||||
+}
|
||||
+
|
||||
+static int rtl8211x_mode(struct phy_device *phydev)
|
||||
+{
|
||||
+ u16 val;
|
||||
+
|
||||
+ val = phy_read(phydev, RTL8211x_FIBER_ESR);
|
||||
+ val &= RTL8211x_MODE_MASK;
|
||||
+
|
||||
+ if(val)
|
||||
+ return RTL8211x_MODE_FIBER;
|
||||
+ else
|
||||
+ return RTL8211x_MODE_COPPER;
|
||||
+}
|
||||
+
|
||||
+static int rtl8211x_config_aneg(struct phy_device *phydev)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ struct rtl8211x_priv *priv = phydev->priv;
|
||||
+
|
||||
+ ret = genphy_read_abilities(phydev);
|
||||
+ if(ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ linkmode_copy(phydev->advertising, phydev->supported);
|
||||
+
|
||||
+ if (rtl8211x_mode(phydev) == RTL8211x_MODE_FIBER) {
|
||||
+ dev_info(&phydev->mdio.dev, "Fiber Mode");
|
||||
+ priv->lastmode = RTL8211x_MODE_FIBER;
|
||||
+ return genphy_c37_config_aneg(phydev);
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&phydev->mdio.dev, "Copper Mode");
|
||||
+
|
||||
+ priv->lastmode = RTL8211x_MODE_COPPER;
|
||||
+
|
||||
+ return genphy_config_aneg(phydev);
|
||||
+}
|
||||
+
|
||||
+static int rtl8211x_read_status(struct phy_device *phydev)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct rtl8211x_priv *priv = phydev->priv;
|
||||
+
|
||||
+ if(rtl8211x_mode(phydev) != priv->lastmode) {
|
||||
+ ret = rtl8211x_config_aneg(phydev);
|
||||
+ if(ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = genphy_restart_aneg(phydev);
|
||||
+ if(ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (rtl8211x_mode(phydev) == RTL8211x_MODE_FIBER)
|
||||
+ return genphy_c37_read_status(phydev);
|
||||
+
|
||||
+ return genphy_read_status(phydev);
|
||||
+}
|
||||
+
|
||||
static struct phy_driver realtek_drvs[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(0x00008201),
|
||||
@@ -495,8 +588,12 @@ static struct phy_driver realtek_drvs[] = {
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc914),
|
||||
.name = "RTL8211DN Gigabit Ethernet",
|
||||
+ .probe = rtl8211x_probe,
|
||||
+ .remove = rtl8211x_remove,
|
||||
.ack_interrupt = rtl821x_ack_interrupt,
|
||||
.config_intr = rtl8211e_config_intr,
|
||||
+ .config_aneg = rtl8211x_config_aneg,
|
||||
+ .read_status = rtl8211x_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
@@ -514,9 +611,13 @@ static struct phy_driver realtek_drvs[] = {
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc916),
|
||||
.name = "RTL8211F Gigabit Ethernet",
|
||||
+ .probe = rtl8211x_probe,
|
||||
+ .remove = rtl8211x_remove,
|
||||
.config_init = &rtl8211f_config_init,
|
||||
.ack_interrupt = &rtl8211f_ack_interrupt,
|
||||
.config_intr = &rtl8211f_config_intr,
|
||||
+ .config_aneg = rtl8211x_config_aneg,
|
||||
+ .read_status = rtl8211x_read_status,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.read_page = rtl821x_read_page,
|
Loading…
Reference in New Issue
Block a user