mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-11-09 17:44:43 -06:00
fix: prevent black screen after application upgrades
Serialize service operations and finish migration before starting services. Install the startup script atomically, remove recursive restarts, and keep the migration marker until required changes succeed. Claim video ownership before clearing orphan VENC/VPSS resources, always finish recovery SYS cleanup, and retain resource state on teardown failures. Rebuild the bundled libkvm_mmf.so with these fixes. Validated cross-builds, ABI and recovery failure paths, plus a 2.4.3 to 2.5.3 upgrade on hardware with 1080p browser WebRTC and MJPEG playback.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
#!/bin/sh
|
||||
# nanokvm Rev3.1
|
||||
|
||||
exec 9>/run/nanokvm-service.lock || exit 1
|
||||
flock -n 9 || { echo "NanoKVM service operation already in progress" >&2; exit 1; }
|
||||
|
||||
wait_for_exit() {
|
||||
process="$1"
|
||||
timeout="$2"
|
||||
@@ -34,43 +37,42 @@ stop_process() {
|
||||
fi
|
||||
|
||||
killall -KILL "$process" 2>/dev/null || true
|
||||
wait_for_exit "$process" 2 || true
|
||||
wait_for_exit "$process" 2 || {
|
||||
echo "Failed to stop $process" >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
stop_services() {
|
||||
# The server owns VI/VPSS. Let it release MMF before stopping kvm_system.
|
||||
stop_process NanoKVM-Server
|
||||
stop_process kvm_system
|
||||
rm -rf /tmp/kvm_system /tmp/server
|
||||
stop_process NanoKVM-Server || return 1
|
||||
stop_process kvm_system || return 1
|
||||
}
|
||||
|
||||
start_services() {
|
||||
cp -r /kvmapp/kvm_system /tmp/
|
||||
if pidof NanoKVM-Server >/dev/null 2>&1 && pidof kvm_system >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
if pidof NanoKVM-Server >/dev/null 2>&1 || pidof kvm_system >/dev/null 2>&1; then
|
||||
echo "NanoKVM is partially running; use restart" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -rf /tmp/kvm_system /tmp/server || return 1
|
||||
cp -r /kvmapp/kvm_system /tmp/ || return 1
|
||||
if [ -f /kvmapp/kvm_new_app ]; then
|
||||
touch /tmp/.nanokvm_migrating
|
||||
/tmp/kvm_system/kvm_system &
|
||||
|
||||
# The legacy migration invokes this init script recursively and starts
|
||||
# the server itself. Wait for that single migration path to finish.
|
||||
migration_wait=0
|
||||
while [ "$migration_wait" -lt 30 ]; do
|
||||
if [ ! -f /kvmapp/kvm_new_app ] && pidof NanoKVM-Server >/dev/null 2>&1; then
|
||||
rm -f /tmp/.nanokvm_migrating
|
||||
return
|
||||
fi
|
||||
sleep 1
|
||||
migration_wait=$((migration_wait + 1))
|
||||
done
|
||||
rm -f /tmp/.nanokvm_migrating
|
||||
else
|
||||
/tmp/kvm_system/kvm_system &
|
||||
/tmp/kvm_system/kvm_system --migrate 9>&-
|
||||
case "$?" in
|
||||
0) ;;
|
||||
2) sync; reboot; return "$?" ;;
|
||||
*) echo "NanoKVM migration failed" >&2; return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! pidof NanoKVM-Server >/dev/null 2>&1; then
|
||||
rm -rf /tmp/server
|
||||
cp -r /kvmapp/server /tmp/
|
||||
/tmp/server/NanoKVM-Server &
|
||||
fi
|
||||
cp -r /kvmapp/server /tmp/ || return 1
|
||||
# Daemons must not inherit the service-operation lock.
|
||||
/tmp/kvm_system/kvm_system 9>&- &
|
||||
/tmp/server/NanoKVM-Server 9>&- &
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
@@ -118,20 +120,17 @@ case "$1" in
|
||||
fi
|
||||
|
||||
# Start services
|
||||
start_services
|
||||
start_services || exit 1
|
||||
;;
|
||||
|
||||
stop)
|
||||
stop_services
|
||||
stop_services || exit 1
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
restart)
|
||||
if [ -f /tmp/.nanokvm_migrating ]; then
|
||||
exit 0
|
||||
fi
|
||||
stop_services
|
||||
start_services
|
||||
stop_services || exit 1
|
||||
start_services || exit 1
|
||||
|
||||
sync
|
||||
echo "OK"
|
||||
|
||||
Binary file not shown.
@@ -5,12 +5,19 @@
|
||||
#include "sample_comm.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/cvi_vc_drv_ioctl.h>
|
||||
|
||||
namespace kvm_mmf {
|
||||
namespace {
|
||||
@@ -37,6 +44,8 @@ SAMPLE_VI_CONFIG_S vi_config = {};
|
||||
bool system_ready = false, group_created = false, group_started = false;
|
||||
bool vi_bound = false, vi_started = false;
|
||||
uint64_t next_token[2] = {}, last_pts[2] = {};
|
||||
int owner_fd = -1; // Held until process exit, including across HDMI restarts.
|
||||
bool stale_resources_cleared = false;
|
||||
|
||||
int channel_id(Codec codec) { return codec == H264 ? 0 : 1; }
|
||||
bool valid_codec(Codec codec) { return codec == H264 || codec == MJPEG; }
|
||||
@@ -48,6 +57,64 @@ bool check(int result, const char *operation)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool unbind_source(MOD_ID_E module, int device, int channel)
|
||||
{
|
||||
MMF_CHN_S source = {module, device, channel};
|
||||
MMF_BIND_DEST_S destinations = {};
|
||||
if (!check(CVI_SYS_GetBindbySrc(&source, &destinations), "GetBindbySrc")) return false;
|
||||
for (unsigned i = 0; i < destinations.u32Num; ++i) {
|
||||
if (!check(CVI_SYS_UnBind(&source, &destinations.astMmfChn[i]), "UnBind stale stream")) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clear_stale_encoder(int channel)
|
||||
{
|
||||
char device[32];
|
||||
snprintf(device, sizeof(device), "/dev/%s%d", CVI_VC_DRV_ENCODER_DEV_NAME, channel);
|
||||
int fd = open(device, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) return check(CVI_FAILURE, "open stale encoder");
|
||||
VENC_CHN_ATTR_S attr = {};
|
||||
int result = ioctl(fd, CVI_VC_VENC_GET_CHN_ATTR, &attr);
|
||||
if (result == CVI_SUCCESS) {
|
||||
fprintf(stderr, "[kvm_mmf] clearing stale VENC channel %d\n", channel);
|
||||
// The SDK wrapper counts channels created in this process. Its
|
||||
// DestroyChn cannot adopt an orphan without corrupting that count.
|
||||
// Use the SDK's kernel ABI only for recovery of the previous owner.
|
||||
result = ioctl(fd, CVI_VC_VENC_STOP_RECV_FRAME);
|
||||
if (result == CVI_SUCCESS) result = ioctl(fd, CVI_VC_VENC_RESET_CHN);
|
||||
if (result == CVI_SUCCESS) result = ioctl(fd, CVI_VC_VENC_DESTROY_CHN);
|
||||
} else if (result == CVI_ERR_VENC_UNEXIST) {
|
||||
result = CVI_SUCCESS;
|
||||
}
|
||||
close(fd);
|
||||
return check(result, "clear stale VENC channel");
|
||||
}
|
||||
|
||||
bool clear_stale_resources()
|
||||
{
|
||||
if (!unbind_source(CVI_ID_VI, 0, 0)) return false;
|
||||
for (int channel = 0; channel < VPSS_MAX_CHN_NUM; ++channel) {
|
||||
if (!unbind_source(CVI_ID_VPSS, group, channel)) return false;
|
||||
}
|
||||
for (int channel = 0; channel < 2; ++channel) {
|
||||
if (!clear_stale_encoder(channel)) return false;
|
||||
}
|
||||
VPSS_GRP_ATTR_S attr = {};
|
||||
int result = CVI_VPSS_GetGrpAttr(group, &attr);
|
||||
if (result == CVI_SUCCESS) {
|
||||
fprintf(stderr, "[kvm_mmf] clearing stale VPSS group %d\n", group);
|
||||
for (int channel = 0; channel < VPSS_MAX_CHN_NUM; ++channel) {
|
||||
if (!check(CVI_VPSS_DisableChn(group, channel), "Disable stale VPSS channel")) return false;
|
||||
}
|
||||
if (!check(CVI_VPSS_StopGrp(group), "Stop stale VPSS group") ||
|
||||
!check(CVI_VPSS_DestroyGrp(group), "Destroy stale VPSS group")) return false;
|
||||
} else if (result != CVI_ERR_VPSS_UNEXIST) {
|
||||
return check(result, "Get stale VPSS group");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool release_locked(Codec codec)
|
||||
{
|
||||
Channel &ch = channels[codec];
|
||||
@@ -121,26 +188,55 @@ bool configure_output(Codec codec, uint16_t width, uint16_t height, uint16_t fps
|
||||
return true;
|
||||
}
|
||||
|
||||
void deinitialize_locked()
|
||||
bool deinitialize_locked()
|
||||
{
|
||||
stop_locked(H264);
|
||||
stop_locked(MJPEG);
|
||||
if (vi_bound) check(SAMPLE_COMM_VI_UnBind_VPSS(0, 0, group), "VI_UnBind_VPSS");
|
||||
if (vi_started) {
|
||||
check(SAMPLE_COMM_VI_DestroyIsp(&vi_config), "DestroyIsp");
|
||||
check(SAMPLE_COMM_VI_DestroyVi(&vi_config), "DestroyVi");
|
||||
bool h264_stopped = stop_locked(H264);
|
||||
bool mjpeg_stopped = stop_locked(MJPEG);
|
||||
if (!h264_stopped || !mjpeg_stopped) return false;
|
||||
if (vi_bound) {
|
||||
if (!check(SAMPLE_COMM_VI_UnBind_VPSS(0, 0, group), "VI_UnBind_VPSS")) return false;
|
||||
vi_bound = false;
|
||||
}
|
||||
if (group_started) check(CVI_VPSS_StopGrp(group), "StopGrp");
|
||||
if (group_created) check(CVI_VPSS_DestroyGrp(group), "DestroyGrp");
|
||||
if (system_ready) SAMPLE_COMM_SYS_Exit();
|
||||
system_ready = group_created = group_started = vi_bound = vi_started = false;
|
||||
channels[H264] = Channel{};
|
||||
channels[MJPEG] = Channel{};
|
||||
if (vi_started) {
|
||||
SAMPLE_COMM_VI_DestroyIsp(&vi_config);
|
||||
SAMPLE_COMM_VI_DestroyVi(&vi_config);
|
||||
vi_started = false;
|
||||
}
|
||||
if (group_started) {
|
||||
if (!check(CVI_VPSS_StopGrp(group), "StopGrp")) return false;
|
||||
group_started = false;
|
||||
}
|
||||
if (group_created) {
|
||||
if (!check(CVI_VPSS_DestroyGrp(group), "DestroyGrp")) return false;
|
||||
group_created = false;
|
||||
}
|
||||
if (system_ready) {
|
||||
if (!check(CVI_SYS_Exit(), "SYS_Exit") || !check(CVI_VB_Exit(), "VB_Exit")) return false;
|
||||
system_ready = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool initialize_locked()
|
||||
{
|
||||
if (vi_started) return true;
|
||||
if (owner_fd < 0) {
|
||||
int fd = open("/run/nanokvm-video.lock", O_CREAT | O_RDWR | O_CLOEXEC, 0600);
|
||||
if (fd < 0 || flock(fd, LOCK_EX | LOCK_NB) != 0) {
|
||||
fprintf(stderr, "[kvm_mmf] cannot acquire video ownership: %s\n", strerror(errno));
|
||||
if (fd >= 0) close(fd);
|
||||
return false;
|
||||
}
|
||||
owner_fd = fd;
|
||||
}
|
||||
if (!stale_resources_cleared) {
|
||||
if (!check(CVI_SYS_Init(), "SYS_Init for recovery")) return false;
|
||||
const bool cleared = clear_stale_resources();
|
||||
const bool exited = check(CVI_SYS_Exit(), "SYS_Exit after recovery");
|
||||
if (!cleared || !exited) return false;
|
||||
stale_resources_cleared = true;
|
||||
}
|
||||
if (system_ready && !deinitialize_locked()) return false;
|
||||
SAMPLE_INI_CFG_S ini = {};
|
||||
PIC_SIZE_E picture;
|
||||
SIZE_S size = {};
|
||||
@@ -278,7 +374,7 @@ bool initialize()
|
||||
bool restart()
|
||||
{
|
||||
std::scoped_lock lock(channel_mutex[H264], channel_mutex[MJPEG]);
|
||||
deinitialize_locked();
|
||||
if (!deinitialize_locked()) return false;
|
||||
return initialize_locked();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,14 @@ using namespace maix::sys;
|
||||
extern kvm_sys_state_t kvm_sys_state;
|
||||
extern kvm_oled_state_t kvm_oled_state;
|
||||
|
||||
static void write_hdmi_state(uint8_t active)
|
||||
static bool write_hdmi_state(uint8_t active)
|
||||
{
|
||||
char temp_path[] = "/kvmapp/kvm/.state.init.XXXXXX";
|
||||
const char *state = active != 0 ? "1\n" : "0\n";
|
||||
int fd = mkstemp(temp_path);
|
||||
if(fd < 0){
|
||||
printf("failed to create HDMI state file: %d\n", errno);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int failure = 0;
|
||||
@@ -40,6 +40,7 @@ static void write_hdmi_state(uint8_t active)
|
||||
unlink(temp_path);
|
||||
printf("failed to publish HDMI state file: %d\n", failure);
|
||||
}
|
||||
return failure == 0;
|
||||
}
|
||||
|
||||
uint8_t get_hdmi_version()
|
||||
@@ -88,38 +89,45 @@ void Production_testing_patch(void)
|
||||
system("sync");
|
||||
}
|
||||
|
||||
void new_app_init(void)
|
||||
static bool init_command(const char *command)
|
||||
{
|
||||
if(system(command) == 0) return true;
|
||||
fprintf(stderr, "[kvms] migration failed: %s\n", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
AppInitResult new_app_init(void)
|
||||
{
|
||||
// Update the necessary scripts
|
||||
system("rm -f /boot/logo.jpeg");
|
||||
system("cp -f /kvmapp/system/update-nanokvm.py /etc/kvm/");
|
||||
if(!init_command("mkdir -p /etc/kvm /kvmapp/kvm")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/update-nanokvm.py /etc/kvm/")) return APP_INIT_FAILED;
|
||||
system("rm -f /etc/init.d/S02udisk");
|
||||
system("cp -f /kvmapp/system/init.d/S00kmod /etc/init.d/");
|
||||
system("cp -f /kvmapp/system/init.d/S01fs /etc/init.d/");
|
||||
system("cp -f /kvmapp/system/init.d/S03usbdev /etc/init.d/");
|
||||
system("cp -f /kvmapp/system/init.d/S15kvmhwd /etc/init.d/");
|
||||
system("cp -f /kvmapp/system/init.d/S30eth /etc/init.d/");
|
||||
system("cp -f /kvmapp/system/init.d/S50sshd /etc/init.d/");
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S00kmod /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S01fs /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S03usbdev /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S15kvmhwd /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S30eth /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S50sshd /etc/init.d/")) return APP_INIT_FAILED;
|
||||
if(kvm_wifi_exist()) {
|
||||
system("cp -f /kvmapp/system/init.d/S30wifi /etc/init.d/");
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S30wifi /etc/init.d/")) return APP_INIT_FAILED;
|
||||
} else {
|
||||
system("rm -f /etc/init.d/S30wifi");
|
||||
}
|
||||
|
||||
// if exit /etc/init.d/S98tailscaled then cp -f /kvmapp/system/init.d/S98tailscaled /etc/init.d/
|
||||
if(access("/etc/init.d/S98tailscaled", F_OK) == 0){
|
||||
system("cp -f /kvmapp/system/init.d/S98tailscaled /etc/init.d/");
|
||||
if(!init_command("cp -f /kvmapp/system/init.d/S98tailscaled /etc/init.d/")) return APP_INIT_FAILED;
|
||||
}
|
||||
|
||||
// rmmod soph_saradc
|
||||
system("rmmod soph_saradc");
|
||||
system("rm -f /mnt/system/ko/soph_saradc.ko");
|
||||
|
||||
// PCIe Patch
|
||||
// system("cp /kvmapp/system/init.d/S95nanokvm /etc/init.d/");
|
||||
if(access("/kvmapp/jpg_stream/dl_lib/libmaixcam_lib.so", F_OK) != 0){
|
||||
system("cp -f /kvmapp/system/init.d/S95nanokvm /etc/init.d/");
|
||||
}
|
||||
// Keep an already running legacy shell on its original script inode.
|
||||
if(!init_command("cp /kvmapp/system/init.d/S95nanokvm /etc/init.d/.S95nanokvm.new && "
|
||||
"chmod 755 /etc/init.d/.S95nanokvm.new && "
|
||||
"mv -f /etc/init.d/.S95nanokvm.new /etc/init.d/S95nanokvm")) return APP_INIT_FAILED;
|
||||
|
||||
// Remove unnecessary components to speed up boot time
|
||||
system("rm -f /etc/init.d/S04backlight");
|
||||
@@ -129,90 +137,45 @@ void new_app_init(void)
|
||||
system("rm -f /etc/init.d/S99*");
|
||||
|
||||
// Add necessary configuration files for program execution
|
||||
system("mkdir /kvmapp/kvm");
|
||||
system("mkdir /etc/kvm");
|
||||
system("echo 0 > /kvmapp/kvm/now_fps");
|
||||
system("echo 30 > /kvmapp/kvm/fps");
|
||||
system("echo 2000 > /kvmapp/kvm/qlty");
|
||||
system("echo h264 > /kvmapp/kvm/type");
|
||||
write_hdmi_state(0);
|
||||
system("touch /etc/kvm/frame_detact");
|
||||
if(!init_command("echo 0 > /kvmapp/kvm/now_fps && echo 30 > /kvmapp/kvm/fps && "
|
||||
"echo 2000 > /kvmapp/kvm/qlty && echo h264 > /kvmapp/kvm/type && "
|
||||
"touch /etc/kvm/frame_detact")) return APP_INIT_FAILED;
|
||||
if(!write_hdmi_state(0)) return APP_INIT_FAILED;
|
||||
|
||||
// rm jpg_stream & kvm_stream
|
||||
system("rm -rf /kvmapp/jpg_stream");
|
||||
system("rm -f /kvmapp/kvm_system/kvm_stream"); // Cannot delete temporarily; the old production test script uses this file to determine if the download is complete
|
||||
|
||||
system("rm -f /kvmapp/kvm_new_app");
|
||||
system("sync");
|
||||
// system("/etc/init.d/S95nanokvm restart");
|
||||
|
||||
// update ko
|
||||
FILE *fp;
|
||||
uint8_t RW_Data_0[30];
|
||||
uint8_t RW_Data_1[30];
|
||||
fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 086ed01749188975afaa40fb569374f8 | awk '{print $2}'", "r");
|
||||
if ( NULL == fp )
|
||||
{
|
||||
pclose(fp);
|
||||
// return;
|
||||
}
|
||||
fgets((char*)RW_Data_0, 10, fp);
|
||||
pclose(fp);
|
||||
fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 69be7eeded3777f750480a5dd5a1aa26 | awk '{print $2}'", "r");
|
||||
if ( NULL == fp )
|
||||
{
|
||||
pclose(fp);
|
||||
// return;
|
||||
}
|
||||
fgets((char*)RW_Data_1, 10, fp);
|
||||
pclose(fp);
|
||||
FILE *fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko", "r");
|
||||
if(!fp) return APP_INIT_FAILED;
|
||||
char digest[33] = {};
|
||||
bool digest_read = fscanf(fp, "%32s", digest) == 1;
|
||||
int digest_status = pclose(fp);
|
||||
if(!digest_read || digest_status != 0) return APP_INIT_FAILED;
|
||||
|
||||
int8_t hdmi_ver = -1;
|
||||
|
||||
if(access("/etc/kvm/hdmi_version", F_OK) == 0){
|
||||
uint8_t RW_Data[2];
|
||||
FILE *fp = fopen("/etc/kvm/hdmi_version", "r");
|
||||
fread(RW_Data, sizeof(char), 2, fp);
|
||||
if(!fp) return APP_INIT_FAILED;
|
||||
int version = fgetc(fp);
|
||||
fclose(fp);
|
||||
if(RW_Data[0] == 'c') hdmi_ver = 1;
|
||||
else if(RW_Data[0] == 'u') hdmi_ver = 2;
|
||||
else if(RW_Data[0] == 'd') hdmi_ver = 2;
|
||||
if(version == EOF) return APP_INIT_FAILED;
|
||||
if(version == 'c') hdmi_ver = 1;
|
||||
else if(version == 'u' || version == 'd') hdmi_ver = 2;
|
||||
}
|
||||
|
||||
// system("/etc/init.d/S03usbdev stop_start");
|
||||
create_temp_watchdog();
|
||||
|
||||
if(hdmi_ver == 2){
|
||||
if(RW_Data_1[0] != '/'){
|
||||
system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko");
|
||||
system("sync");
|
||||
system("reboot");
|
||||
} else {
|
||||
system("sync");
|
||||
system("/etc/init.d/S15kvmhwd start");
|
||||
system("/etc/init.d/S95nanokvm restart");
|
||||
}
|
||||
} else {
|
||||
if((RW_Data_0[0] != '/') && (RW_Data_1[0] != '/')){
|
||||
system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko");
|
||||
system("sync");
|
||||
system("reboot");
|
||||
} else {
|
||||
system("sync");
|
||||
system("/etc/init.d/S15kvmhwd start");
|
||||
system("/etc/init.d/S95nanokvm restart");
|
||||
}
|
||||
bool current_driver = strcmp(digest, "69be7eeded3777f750480a5dd5a1aa26") == 0 ||
|
||||
(hdmi_ver != 2 && strcmp(digest, "086ed01749188975afaa40fb569374f8") == 0);
|
||||
if(!current_driver){
|
||||
if(!init_command("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko")) return APP_INIT_FAILED;
|
||||
}
|
||||
|
||||
if(access("/root/old/kvm_new_img", F_OK) == 0){
|
||||
system("rm -r /root/old");
|
||||
}
|
||||
|
||||
system("sync");
|
||||
system("killall NanoKVM-Server");
|
||||
system("rm -r /tmp/server");
|
||||
system("cp -r /kvmapp/server /tmp/");
|
||||
system("/tmp/server/NanoKVM-Server &");
|
||||
if(unlink("/kvmapp/kvm_new_app") != 0) return APP_INIT_FAILED;
|
||||
sync();
|
||||
return current_driver ? APP_INIT_OK : APP_INIT_REBOOT;
|
||||
}
|
||||
|
||||
void build_complete_resolv(void)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#include "config.h"
|
||||
|
||||
void new_img_init(void);
|
||||
void new_app_init(void);
|
||||
enum AppInitResult { APP_INIT_OK = 0, APP_INIT_FAILED = 1, APP_INIT_REBOOT = 2 };
|
||||
AppInitResult new_app_init(void);
|
||||
void Production_testing_patch(void);
|
||||
|
||||
#endif // SYSTEM_INIT_H_
|
||||
|
||||
@@ -192,10 +192,15 @@ int main(int argc, char* argv[])
|
||||
new_img_init();
|
||||
}
|
||||
|
||||
// Execute only when it's a new app
|
||||
const bool migrate_only = argc == 2 && strcmp(argv[1], "--migrate") == 0;
|
||||
if(access("/kvmapp/kvm_new_app", F_OK) == 0){
|
||||
new_app_init();
|
||||
AppInitResult result = new_app_init();
|
||||
if(migrate_only || result == APP_INIT_FAILED) return result;
|
||||
// A legacy init script starts us without --migrate and can still be
|
||||
// copying the server. Boot once into the newly installed init script.
|
||||
return system("reboot") == 0 ? 0 : 1;
|
||||
}
|
||||
if(migrate_only) return APP_INIT_OK;
|
||||
|
||||
// only for production testing
|
||||
if (access("/tmp/S49kvmtest", F_OK) == 0){
|
||||
|
||||
Reference in New Issue
Block a user