Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
108
tundra/boot/init.c
Normal file
108
tundra/boot/init.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/* SPDX-License-Identifier: MPL-2.0
|
||||
* Stage-zero diagnostic init. No disks, network or Android framework.
|
||||
* Keep this executable independent of libc to use it on both test targets.
|
||||
*/
|
||||
#if defined(__x86_64__)
|
||||
#define NR_write 1
|
||||
#define NR_read 0
|
||||
#define NR_close 3
|
||||
#define NR_openat 257
|
||||
#define NR_mount 165
|
||||
#define NR_getpid 39
|
||||
#define NR_exit 60
|
||||
#define NR_reboot 169
|
||||
#define NR_nanosleep 35
|
||||
static long call(long n, long a, long b, long c, long d, long e) {
|
||||
register long r10 __asm__("r10") = d;
|
||||
register long r8 __asm__("r8") = e;
|
||||
long result;
|
||||
__asm__ volatile("syscall" : "=a"(result)
|
||||
: "a"(n), "D"(a), "S"(b), "d"(c), "r"(r10), "r"(r8)
|
||||
: "rcx", "r11", "memory");
|
||||
return result;
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
#define NR_write 64
|
||||
#define NR_read 63
|
||||
#define NR_close 57
|
||||
#define NR_openat 56
|
||||
#define NR_mount 40
|
||||
#define NR_getpid 172
|
||||
#define NR_exit 93
|
||||
#define NR_reboot 142
|
||||
#define NR_nanosleep 101
|
||||
static long call(long n, long a, long b, long c, long d, long e) {
|
||||
register long x8 __asm__("x8") = n;
|
||||
register long x0 __asm__("x0") = a;
|
||||
register long x1 __asm__("x1") = b;
|
||||
register long x2 __asm__("x2") = c;
|
||||
register long x3 __asm__("x3") = d;
|
||||
register long x4 __asm__("x4") = e;
|
||||
__asm__ volatile("svc 0" : "+r"(x0)
|
||||
: "r"(x8), "r"(x1), "r"(x2), "r"(x3), "r"(x4)
|
||||
: "memory");
|
||||
return x0;
|
||||
}
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
|
||||
static void say(const char *s) {
|
||||
long n = 0;
|
||||
while (s[n]) ++n;
|
||||
while (n > 0) {
|
||||
long written = call(NR_write, 1, (long)s, n, 0, 0);
|
||||
if (written <= 0) break;
|
||||
s += written;
|
||||
n -= written;
|
||||
}
|
||||
}
|
||||
|
||||
static int contains(const char *s, const char *needle) {
|
||||
for (; *s; ++s) {
|
||||
long i = 0;
|
||||
while (needle[i] && s[i] == needle[i]) ++i;
|
||||
if (!needle[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void file(const char *path, char *buffer, long capacity) {
|
||||
long fd = call(NR_openat, -100, (long)path, 0, 0, 0);
|
||||
buffer[0] = 0;
|
||||
if (fd < 0) return;
|
||||
long n = call(NR_read, fd, (long)buffer, capacity - 1, 0, 0);
|
||||
if (n > 0) buffer[n] = 0;
|
||||
call(NR_close, fd, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _start(void) {
|
||||
if (call(NR_getpid, 0, 0, 0, 0, 0) != 1) {
|
||||
say("Tundra init must only run as PID 1 in the diagnostic ramdisk.\n");
|
||||
call(NR_exit, 2, 0, 0, 0, 0);
|
||||
for (;;) {}
|
||||
}
|
||||
say("TUNDRA_STAGE0_START\n");
|
||||
long proc = call(NR_mount, (long)"proc", (long)"/proc", (long)"proc", 14, 0);
|
||||
long sys = call(NR_mount, (long)"sysfs", (long)"/sys", (long)"sysfs", 14, 0);
|
||||
char buffer[4096];
|
||||
file("/proc/version", buffer, sizeof(buffer));
|
||||
say(buffer);
|
||||
file("/proc/cmdline", buffer, sizeof(buffer));
|
||||
int selftest = contains(buffer, "tundra.selftest=1");
|
||||
if (proc == 0 && sys == 0 && buffer[0]) {
|
||||
say("TUNDRA_STAGE0_OK pid1 proc sysfs cmdline\n");
|
||||
} else {
|
||||
say("TUNDRA_STAGE0_FAILED pseudo-filesystems\n");
|
||||
}
|
||||
say("Diagnostic only: no Gecko, Gaia, HAL, USB service or persistent mounts.\n");
|
||||
if (selftest) {
|
||||
say("TUNDRA_STAGE0_POWEROFF\n");
|
||||
call(NR_reboot, 0xfee1dead, 672274793, 0x4321fedc, 0, 0);
|
||||
}
|
||||
for (;;) {
|
||||
long delay[2] = {15, 0};
|
||||
call(NR_nanosleep, (long)delay, 0, 0, 0, 0);
|
||||
say("TUNDRA_STAGE0_ALIVE\n");
|
||||
}
|
||||
}
|
||||
82
tundra/boot/native-root.sh
Executable file
82
tundra/boot/native-root.sh
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
# Called by rescue PID 1 only after the read-only storage check succeeds.
|
||||
set -eu
|
||||
# BUILD_TIME_FLOOR
|
||||
# RUNTIME_CONFIG_OVERLAY
|
||||
# A kernel fallback date must not precede the build; RTC is not modified.
|
||||
if [ "$(date +%s)" -lt "${BUILD_EPOCH:-0}" ]; then date -s "@$BUILD_EPOCH"; fi
|
||||
trap 'echo TUNDRA_NATIVE_SETUP_FAILED; while :; do /bin/busybox sleep 5; done' EXIT
|
||||
LOWER=/installed/home/droidian/vulpes-tundra-tests/runtime-reference-20260925/root
|
||||
if [ -n "${SYSTEM_IMAGE:-}" ]; then
|
||||
test "$(sha256sum "$SYSTEM_IMAGE" | cut -d' ' -f1)" = "$SYSTEM_IMAGE_SHA"
|
||||
mkdir -p /run/tundra-system
|
||||
mount -t ext4 -o loop,ro,noload "$SYSTEM_IMAGE" /run/tundra-system
|
||||
LOWER=/run/tundra-system
|
||||
fi
|
||||
test -f "$LOWER/etc/systemd/system/tundra.target"
|
||||
UPPER=/run/native-upper
|
||||
WORK=/run/native-work
|
||||
if [ -n "${STATE_IMAGE:-}" ]; then
|
||||
test -f "$STATE_IMAGE" && test ! -L "$STATE_IMAGE"
|
||||
test "$(stat -c %s "$STATE_IMAGE")" = "$STATE_BYTES"
|
||||
blkid "$STATE_IMAGE" | grep -F "UUID=\"$STATE_UUID\"" >/dev/null
|
||||
repaired=0
|
||||
e2fsck -p "$STATE_IMAGE" || repaired=$?
|
||||
test "$repaired" -le 1
|
||||
mkdir -p /run/tundra-state
|
||||
mount -t ext4 -o loop,rw,nosuid,nodev "$STATE_IMAGE" /run/tundra-state
|
||||
# A data layer belongs to one immutable system image. Refuse accidental reuse.
|
||||
test "$(cat /run/tundra-state/system.sha256)" = "$SYSTEM_IMAGE_SHA"
|
||||
UPPER=/run/tundra-state/upper
|
||||
WORK=/run/tundra-state/work
|
||||
fi
|
||||
mkdir -p "$UPPER" "$WORK" /newroot
|
||||
chmod 755 "$UPPER"
|
||||
mount -t overlay overlay -o "lowerdir=$LOWER,upperdir=$UPPER,workdir=$WORK" /newroot
|
||||
if [ -z "${SYSTEM_IMAGE:-}" ] || [ "${APPLY_NATIVE_CONFIG:-0}" = 1 ]; then
|
||||
# Only the selected upper layer is edited; the system image stays read-only.
|
||||
if [ -n "${STATE_IMAGE:-}" ]; then
|
||||
mkdir -p /run/tundra-identity
|
||||
for identity in machine-id passwd group shadow gshadow; do
|
||||
if [ -s "/newroot/etc/$identity" ]; then
|
||||
cp -p "/newroot/etc/$identity" "/run/tundra-identity/$identity"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
rm -f /newroot/etc/tundra/hardware-enabled /newroot/etc/systemd/system/tundra.target.wants/ofono.service /newroot/etc/systemd/system/tundra.target.wants/tundra-audio.service /newroot/etc/tundra/network-enabled /newroot/etc/systemd/system/tundra.target.wants/NetworkManager.service /newroot/etc/systemd/system/tundra.target.wants/tundra-wifi.service
|
||||
tar -xf /native-config.tar -C /newroot
|
||||
if [ -d /run/tundra-identity ]; then
|
||||
for identity in /run/tundra-identity/*; do
|
||||
[ -f "$identity" ] && cp -p "$identity" /newroot/etc/
|
||||
done
|
||||
chmod 644 /newroot/etc/machine-id
|
||||
fi
|
||||
fi
|
||||
if [ -f /shared-ui.tar ]; then tar -xf /shared-ui.tar -C /newroot; fi
|
||||
# A previous successful session must never count as proof of this boot.
|
||||
for log in test.json home.png session.pid gecko.log server.log compositor.log network-gecko.json wifi-ui.json; do
|
||||
rm -f "/newroot/opt/vulpes/logs/$log"
|
||||
done
|
||||
mkdir -p /newroot/reference /newroot/run /newroot/root/.ssh
|
||||
if [ -z "${SYSTEM_IMAGE:-}" ]; then
|
||||
: > /newroot/reference/android-rootfs.img
|
||||
mount --bind /installed/var/lib/lxc/android/android-rootfs.img /newroot/reference/android-rootfs.img
|
||||
else
|
||||
test -s /newroot/reference/android-rootfs.img
|
||||
fi
|
||||
# Installed lower layers stay reachable for the overlay/loop driver until reboot.
|
||||
mkdir -p /newroot/reference/installed
|
||||
mount --move /installed /newroot/reference/installed
|
||||
# Keep a minimal, already tested rescue environment in RAM. Its SSH account
|
||||
# does not depend on PAM/NSS/shell configuration in the experimental root.
|
||||
mkdir -p /run/rescue-root
|
||||
(cd / && tar -c bin sbin lib etc root) | (cd /run/rescue-root && tar -x)
|
||||
mkdir -p /run/rescue-root/dev /run/rescue-root/proc /run/rescue-root/run
|
||||
mount --rbind /dev /run/rescue-root/dev
|
||||
mount --bind /proc /run/rescue-root/proc
|
||||
kill "$(cat /run/dropbear.pid)"
|
||||
chroot /run/rescue-root /sbin/dropbear -E -s -j -k -p 10.15.19.82:2222 -r /etc/tundra-hostkey -P /run/dropbear.pid
|
||||
for fs in dev proc sys run; do mount --move "/$fs" "/newroot/$fs"; done
|
||||
# A static watchdog survives switch_root without needing the old /bin or /proc.
|
||||
exec switch_root /newroot /sbin/init --unit=tundra.target
|
||||
55
tundra/boot/rescue-init.sh
Executable file
55
tundra/boot/rescue-init.sh
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/busybox sh
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
# Temporary RAM-only boot. Installed data is never mounted writable.
|
||||
export PATH=/bin:/sbin
|
||||
/bin/busybox --install -s /bin
|
||||
mount -t proc proc /proc
|
||||
ln -s /proc/mounts /etc/mtab
|
||||
mount -t sysfs sysfs /sys
|
||||
mount -t devtmpfs devtmpfs /dev
|
||||
mkdir -p /dev/pts /run /sys/kernel/config
|
||||
mount -t devpts devpts /dev/pts
|
||||
mount -t tmpfs tmpfs /run
|
||||
exec >>/run/boot.log 2>&1
|
||||
# This runs before USB/storage setup, so a later failure still returns to Droidian.
|
||||
(sleep 480; echo 'Tundra trial deadline reached'; reboot -f) &
|
||||
echo TUNDRA_RESCUE_STARTED
|
||||
case "$(cat /proc/cmdline)" in *tundra.rescue=1*) ;; *) reboot -f;; esac
|
||||
mdev -s
|
||||
chmod 666 /dev/null /dev/zero /dev/random /dev/urandom /dev/ptmx
|
||||
mount -t configfs configfs /sys/kernel/config
|
||||
G=/sys/kernel/config/usb_gadget/tundra
|
||||
mkdir -p "$G"
|
||||
echo 0x1d6b > "$G/idVendor"
|
||||
echo 0x0104 > "$G/idProduct"
|
||||
mkdir -p "$G/strings/0x409" "$G/configs/c.1/strings/0x409" "$G/functions/rndis.usb0"
|
||||
echo TUNDRA-TRIAL > "$G/strings/0x409/serialnumber"
|
||||
echo 'Tundra development' > "$G/strings/0x409/manufacturer"
|
||||
echo 'Temporary runtime trial' > "$G/strings/0x409/product"
|
||||
echo 250 > "$G/configs/c.1/MaxPower"
|
||||
ln -s "$G/functions/rndis.usb0" "$G/configs/c.1/rndis"
|
||||
for i in $(seq 1 100); do
|
||||
UDC=$(ls /sys/class/udc | head -n1)
|
||||
[ -n "$UDC" ] && break
|
||||
sleep 0.1
|
||||
done
|
||||
echo "$UDC" > "$G/UDC"
|
||||
ip link set lo up
|
||||
for iface in rndis0 usb0; do
|
||||
if [ -d "/sys/class/net/$iface" ]; then
|
||||
ip addr add 10.15.19.82/24 dev "$iface"
|
||||
ip link set "$iface" up
|
||||
break
|
||||
fi
|
||||
done
|
||||
/sbin/dropbear -E -s -j -k -p 10.15.19.82:2222 -r /etc/tundra-hostkey -P /run/dropbear.pid
|
||||
echo TUNDRA_USB_SSH_READY
|
||||
# No LVM activation, fsck, journal replay, resizing, or writes to a block device.
|
||||
if [ -b /dev/mmcblk0p72 ] && [ "$(dd if=/dev/mmcblk0p72 bs=1048576 count=1 2>/dev/null | sha256sum | cut -d' ' -f1)" = "$EXPECTED_STORAGE_HASH" ]; then
|
||||
mkdir -p /dev/mapper /installed
|
||||
/sbin/dmsetup create tundra-installed-ro --readonly --table '0 104448000 linear /dev/mmcblk0p72 329728'
|
||||
/sbin/dmsetup mknodes
|
||||
mount -t ext4 -o ro,noload /dev/mapper/tundra-installed-ro /installed
|
||||
fi
|
||||
echo TUNDRA_RESCUE_READY
|
||||
while :; do sleep 5; done
|
||||
132
tundra/boot/usb-init.c
Normal file
132
tundra/boot/usb-init.c
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* SPDX-License-Identifier: MPL-2.0
|
||||
* Read-only, development-only USB diagnostics over Linux FunctionFS.
|
||||
* No shell, block-device access, reboot command or arbitrary file service.
|
||||
*/
|
||||
#define _start stage0_start
|
||||
#include "init.c"
|
||||
#undef _start
|
||||
#if defined(__x86_64__)
|
||||
#define NR_mkdirat 258
|
||||
#define NR_symlinkat 266
|
||||
#define NR_getdents64 217
|
||||
#else
|
||||
#define NR_mkdirat 34
|
||||
#define NR_symlinkat 36
|
||||
#define NR_getdents64 61
|
||||
#endif
|
||||
#define G "/sys/kernel/config/usb_gadget/tundra"
|
||||
typedef unsigned int u32;
|
||||
static long length(const char *s) { long n=0; while(s[n]) ++n; return n; }
|
||||
static void pause_ms(long ms) {
|
||||
long t[2]={ms/1000,(ms%1000)*1000000}; call(NR_nanosleep,(long)t,0,0,0,0);
|
||||
}
|
||||
static void fail(const char *s) {
|
||||
say("TUNDRA_USB_FAILED ");say(s);say("\n");
|
||||
for (;;) pause_ms(10000);
|
||||
}
|
||||
static void directory(const char *p) {
|
||||
long r=call(NR_mkdirat,-100,(long)p,0755,0,0);
|
||||
if(r<0 && r!=-17) fail(p);
|
||||
}
|
||||
static void put(const char *p,const char *value) {
|
||||
long fd=call(NR_openat,-100,(long)p,1,0,0);
|
||||
if(fd<0) fail(p);
|
||||
long n=length(value);
|
||||
if(call(NR_write,fd,(long)value,n,0,0)!=n) fail(p);
|
||||
call(NR_close,fd,0,0,0,0);
|
||||
}
|
||||
static void send(long fd,const char *value) {
|
||||
long n=length(value);
|
||||
while(n) {
|
||||
long r=call(NR_write,fd,(long)value,n,0,0);
|
||||
if(r<=0) return;
|
||||
n-=r;value+=r;
|
||||
}
|
||||
}
|
||||
static int equal(const char *a,const char *b) {
|
||||
while(*a && *b && *a==*b) {++a;++b;}return *a==*b;
|
||||
}
|
||||
static const unsigned char descriptors[]={
|
||||
/* v2 header: magic, length, FS+HS+SS flags and descriptor counts */
|
||||
3,0,0,0, 105,0,0,0, 7,0,0,0, 3,0,0,0, 3,0,0,0, 5,0,0,0,
|
||||
9,4,0,0,2,255,0,0,1, 7,5,0x81,2,64,0,0, 7,5,0x02,2,64,0,0,
|
||||
9,4,0,0,2,255,0,0,1, 7,5,0x81,2,0,2,0, 7,5,0x02,2,0,2,0,
|
||||
9,4,0,0,2,255,0,0,1,
|
||||
7,5,0x81,2,0,4,0, 6,48,0,0,0,0,
|
||||
7,5,0x02,2,0,4,0, 6,48,0,0,0,0
|
||||
};
|
||||
static const struct __attribute__((packed)) {
|
||||
u32 magic,length,count,languages;
|
||||
unsigned short language;
|
||||
char name[18];
|
||||
} strings={2,36,1,1,0x0409,"Tundra diagnostic"};
|
||||
static void bind_udc(void) {
|
||||
char data[4096];
|
||||
for(int retry=0;retry<300;retry++) {
|
||||
long fd=call(NR_openat,-100,(long)"/sys/class/udc",0,0,0);
|
||||
if(fd>=0) {
|
||||
long n=call(NR_getdents64,fd,(long)data,sizeof(data),0,0);
|
||||
call(NR_close,fd,0,0,0,0);
|
||||
for(long i=0;i+19<n;) {
|
||||
unsigned short size=*(unsigned short *)(data+i+16);
|
||||
if(size<20 || i+size>n) break;
|
||||
char *name=data+i+19;
|
||||
if(name[0]!='.') {put(G "/UDC",name);say("TUNDRA_USB_BOUND ");say(name);say("\n");return;}
|
||||
i+=size;
|
||||
}
|
||||
}
|
||||
pause_ms(100);
|
||||
}
|
||||
fail("no USB device controller");
|
||||
}
|
||||
__attribute__((noreturn)) void _start(void) {
|
||||
if(call(NR_getpid,0,0,0,0,0)!=1) {
|
||||
say("USB diagnostic must be PID 1 in its diagnostic environment.\n");
|
||||
call(NR_exit,2,0,0,0,0);for(;;){}
|
||||
}
|
||||
call(NR_mount,(long)"proc",(long)"/proc",(long)"proc",14,0);
|
||||
char buffer[4096];file("/proc/cmdline",buffer,sizeof(buffer));
|
||||
if(!contains(buffer,"tundra.usb=1")) fail("explicit kernel flag required");
|
||||
call(NR_mount,(long)"sysfs",(long)"/sys",(long)"sysfs",14,0);
|
||||
/* Sargo's stock kernel has no devtmpfs. FunctionFS creates its own nodes. */
|
||||
if(call(NR_mount,(long)"tmpfs",(long)"/dev",(long)"tmpfs",2,0)<0) fail("dev tmpfs");
|
||||
directory("/sys/kernel/config");
|
||||
if(call(NR_mount,(long)"configfs",(long)"/sys/kernel/config",(long)"configfs",14,0)<0) fail("configfs");
|
||||
directory(G);
|
||||
/* Linux development gadget IDs, not an assigned Vulpes product identity. */
|
||||
put(G "/idVendor","0x1d6b");put(G "/idProduct","0x0104");
|
||||
put(G "/bcdUSB","0x0300");
|
||||
directory(G "/strings/0x409");
|
||||
put(G "/strings/0x409/manufacturer","Tundra development");
|
||||
put(G "/strings/0x409/product","Read-only boot diagnostic");
|
||||
put(G "/strings/0x409/serialnumber","TUNDRA-DIAG");
|
||||
directory(G "/configs/c.1");put(G "/configs/c.1/MaxPower","250");
|
||||
directory(G "/functions/ffs.tundra");directory("/dev/ffs-tundra");
|
||||
if(call(NR_mount,(long)"tundra",(long)"/dev/ffs-tundra",(long)"functionfs",0,0)<0) fail("FunctionFS mount");
|
||||
long ep0=call(NR_openat,-100,(long)"/dev/ffs-tundra/ep0",2|2048,0,0);
|
||||
if(ep0<0 || call(NR_write,ep0,(long)descriptors,sizeof(descriptors),0,0)!=sizeof(descriptors)) fail("descriptors");
|
||||
if(call(NR_write,ep0,(long)&strings,sizeof(strings),0,0)!=sizeof(strings)) fail("strings");
|
||||
if(call(NR_symlinkat,(long)G "/functions/ffs.tundra",-100,(long)G "/configs/c.1/diagnostic",0,0)<0) fail("function link");
|
||||
bind_udc();
|
||||
long input=call(NR_openat,-100,(long)"/dev/ffs-tundra/ep2",2048,0,0);
|
||||
long output=call(NR_openat,-100,(long)"/dev/ffs-tundra/ep1",1,0,0);
|
||||
if(input<0 || output<0) fail("endpoints");
|
||||
say("TUNDRA_USB_READY protocol=1 commands=status,version,mounts\n");
|
||||
for(;;) {
|
||||
/* Drain bind/enable events. Unsupported control requests remain stalled. */
|
||||
char events[96];call(NR_read,ep0,(long)events,sizeof(events),0,0);
|
||||
long n=call(NR_read,input,(long)buffer,63,0,0);
|
||||
if(n>0) {
|
||||
buffer[n]=0;
|
||||
const char *path=0;
|
||||
if(equal(buffer,"status\n")) send(output,"TUNDRA_USB_STATUS protocol=1 readOnly=true\nEND\n");
|
||||
else {
|
||||
if(equal(buffer,"version\n")) path="/proc/version";
|
||||
if(equal(buffer,"mounts\n")) path="/proc/mounts";
|
||||
if(path) {file(path,buffer,sizeof(buffer));send(output,buffer);send(output,"\nEND\n");}
|
||||
else send(output,"ERROR unsupported command\nEND\n");
|
||||
}
|
||||
}
|
||||
pause_ms(20);
|
||||
}
|
||||
}
|
||||
14
tundra/boot/watchdog.c
Normal file
14
tundra/boot/watchdog.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: MPL-2.0
|
||||
* Temporary boot deadline. No files are needed after exec, including across
|
||||
* switch_root. Only started as root by the explicit development initramfs.
|
||||
*/
|
||||
#define _start unused_stage0_start
|
||||
#include "init.c"
|
||||
#undef _start
|
||||
__attribute__((noreturn)) void _start(void) {
|
||||
long remaining[2] = {600, 0};
|
||||
while (call(NR_nanosleep, (long)remaining, (long)remaining, 0, 0, 0) == -4) {}
|
||||
say("TUNDRA_TRIAL_DEADLINE_REBOOT\n");
|
||||
call(NR_reboot, 0xfee1dead, 672274793, 0x01234567, 0, 0);
|
||||
for (;;) {long t[2]={1,0};call(NR_nanosleep,(long)t,0,0,0,0);}
|
||||
}
|
||||
Loading…
Reference in a new issue