mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Feature/efi (#2192)
* update makefile * fix * add efi support * fix efi * clean up * add `make update` and `make update-overlay` * more protections * update package lock * rename reflash to indicate it isn't real * fix authcookie * Update product.yaml
This commit is contained in:
4
.github/workflows/product.yaml
vendored
4
.github/workflows/product.yaml
vendored
@@ -134,9 +134,9 @@ jobs:
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
make V=1 embassyos-raspi.img --debug
|
||||
make V=1 eos_raspberrypi-uninit.img --debug
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: image
|
||||
path: embassyos-raspi.img
|
||||
path: eos_raspberrypi-uninit.img
|
||||
|
||||
104
Makefile
104
Makefile
@@ -1,6 +1,6 @@
|
||||
RASPI_TARGETS := embassyos-raspi.img embassyos-raspi.tar.gz gzip lite-upgrade.img
|
||||
ARCH := $(shell if echo $(RASPI_TARGETS) | grep -qw "$(MAKECMDGOALS)"; then echo aarch64; else uname -m; fi)
|
||||
RASPI_TARGETS := eos_raspberrypi-uninit.img eos_raspberrypi-uninit.tar.gz
|
||||
OS_ARCH := $(shell if echo $(RASPI_TARGETS) | grep -qw "$(MAKECMDGOALS)"; then echo raspberrypi; else uname -m; fi)
|
||||
ARCH := $(shell if [ "$(OS_ARCH)" = "raspberrypi" ]; then echo aarch64; else echo $(OS_ARCH); fi)
|
||||
ENVIRONMENT_FILE = $(shell ./check-environment.sh)
|
||||
GIT_HASH_FILE = $(shell ./check-git-hash.sh)
|
||||
VERSION_FILE = $(shell ./check-version.sh)
|
||||
@@ -19,18 +19,28 @@ FRONTEND_DIAGNOSTIC_UI_SRC := $(shell find frontend/projects/diagnostic-ui)
|
||||
FRONTEND_INSTALL_WIZARD_SRC := $(shell find frontend/projects/install-wizard)
|
||||
PATCH_DB_CLIENT_SRC := $(shell find patch-db/client -not -path patch-db/client/dist)
|
||||
GZIP_BIN := $(shell which pigz || which gzip)
|
||||
$(shell sudo true)
|
||||
ALL_TARGETS := $(EMBASSY_BINS) system-images/compat/docker-images/aarch64.tar system-images/utils/docker-images/$(ARCH).tar system-images/binfmt/docker-images/$(ARCH).tar $(EMBASSY_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE)
|
||||
|
||||
ifeq ($(REMOTE),)
|
||||
mkdir = mkdir -p $1
|
||||
rm = rm -rf $@
|
||||
cp = cp -r $1 $2
|
||||
else
|
||||
mkdir = ssh $(REMOTE) 'mkdir -p $1'
|
||||
rm = ssh $(REMOTE) 'rm -rf $@'
|
||||
define cp
|
||||
tar --transform "s|^$1|x|" -czv -f- $1 | ssh $(REMOTE) "sudo tar --transform 's|^x|$2|' -xzv -f- -C /"
|
||||
endef
|
||||
endif
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
.PHONY: all gzip install clean format sdk snapshots frontends ui backend
|
||||
.PHONY: all gzip install clean format sdk snapshots frontends ui backend reflash eos_raspberrypi.img sudo
|
||||
|
||||
all: $(EMBASSY_SRC) $(EMBASSY_BINS) system-images/compat/docker-images/aarch64.tar system-images/utils/docker-images/$(ARCH).tar system-images/binfmt/docker-images/$(ARCH).tar $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE)
|
||||
all: $(ALL_TARGETS)
|
||||
|
||||
gzip: embassyos-raspi.tar.gz
|
||||
|
||||
embassyos-raspi.tar.gz: embassyos-raspi.img
|
||||
tar --format=posix -cS -f- embassyos-raspi.img | $(GZIP_BIN) > embassyos-raspi.tar.gz
|
||||
sudo:
|
||||
sudo true
|
||||
|
||||
clean:
|
||||
rm -f 2022-01-28-raspios-bullseye-arm64-lite.zip
|
||||
@@ -62,7 +72,7 @@ format:
|
||||
sdk:
|
||||
cd backend/ && ./install-sdk.sh
|
||||
|
||||
embassyos-raspi.img: all raspios.img cargo-deps/aarch64-unknown-linux-gnu/release/nc-broadcast cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep
|
||||
eos_raspberrypi-uninit.img: $(ALL_TARGETS) raspios.img cargo-deps/aarch64-unknown-linux-gnu/release/nc-broadcast cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep | sudo
|
||||
! test -f embassyos-raspi.img || rm embassyos-raspi.img
|
||||
./build/raspberry-pi/make-image.sh
|
||||
|
||||
@@ -70,41 +80,63 @@ lite-upgrade.img: raspios.img cargo-deps/aarch64-unknown-linux-gnu/release/nc-br
|
||||
! test -f lite-upgrade.img || rm lite-upgrade.img
|
||||
./build/raspberry-pi/make-upgrade-image.sh
|
||||
|
||||
eos_raspberrypi.img: raspios.img $(BUILD_SRC) eos.raspberrypi.squashfs $(VERSION_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE)
|
||||
eos_raspberrypi.img: raspios.img $(BUILD_SRC) eos.raspberrypi.squashfs $(VERSION_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) | sudo
|
||||
! test -f eos_raspberrypi.img || rm eos_raspberrypi.img
|
||||
./build/raspberry-pi/make-initialized-image.sh
|
||||
|
||||
# For creating os images. DO NOT USE
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)/usr/bin
|
||||
cp backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-init $(DESTDIR)/usr/bin/
|
||||
cp backend/target/$(ARCH)-unknown-linux-gnu/release/embassyd $(DESTDIR)/usr/bin/
|
||||
cp backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-cli $(DESTDIR)/usr/bin/
|
||||
cp backend/target/$(ARCH)-unknown-linux-gnu/release/avahi-alias $(DESTDIR)/usr/bin/
|
||||
install: $(ALL_TARGETS)
|
||||
$(call mkdir,$(DESTDIR)/usr/bin)
|
||||
$(call cp,backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-init,$(DESTDIR)/usr/bin/embassy-init)
|
||||
$(call cp,backend/target/$(ARCH)-unknown-linux-gnu/release/embassyd,$(DESTDIR)/usr/bin/embassyd)
|
||||
$(call cp,backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-cli,$(DESTDIR)/usr/bin/embassy-cli)
|
||||
$(call cp,backend/target/$(ARCH)-unknown-linux-gnu/release/avahi-alias,$(DESTDIR)/usr/bin/avahi-alias)
|
||||
|
||||
mkdir -p $(DESTDIR)/usr/lib
|
||||
rm -rf $(DESTDIR)/usr/lib/embassy
|
||||
cp -r build/lib $(DESTDIR)/usr/lib/embassy
|
||||
$(call mkdir,$(DESTDIR)/usr/lib)
|
||||
$(call rm,$(DESTDIR)/usr/lib/embassy)
|
||||
$(call cp,build/lib,$(DESTDIR)/usr/lib/embassy)
|
||||
|
||||
cp ENVIRONMENT.txt $(DESTDIR)/usr/lib/embassy/
|
||||
cp GIT_HASH.txt $(DESTDIR)/usr/lib/embassy/
|
||||
cp VERSION.txt $(DESTDIR)/usr/lib/embassy/
|
||||
$(call cp,ENVIRONMENT.txt,$(DESTDIR)/usr/lib/embassy/ENVIRONMENT.txt)
|
||||
$(call cp,GIT_HASH.txt,$(DESTDIR)/usr/lib/embassy/GIT_HASH.txt)
|
||||
$(call cp,VERSION.txt,$(DESTDIR)/usr/lib/embassy/VERSION.txt)
|
||||
|
||||
mkdir -p $(DESTDIR)/usr/lib/embassy/container
|
||||
cp libs/target/aarch64-unknown-linux-musl/release/embassy_container_init $(DESTDIR)/usr/lib/embassy/container/embassy_container_init.arm64
|
||||
cp libs/target/x86_64-unknown-linux-musl/release/embassy_container_init $(DESTDIR)/usr/lib/embassy/container/embassy_container_init.amd64
|
||||
$(call mkdir,$(DESTDIR)/usr/lib/embassy/container)
|
||||
$(call cp,libs/target/aarch64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/embassy/container/embassy_container_init.arm64)
|
||||
$(call cp,libs/target/x86_64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/embassy/container/embassy_container_init.amd64)
|
||||
|
||||
mkdir -p $(DESTDIR)/usr/lib/embassy/system-images
|
||||
cp system-images/compat/docker-images/aarch64.tar $(DESTDIR)/usr/lib/embassy/system-images/compat.tar
|
||||
cp system-images/utils/docker-images/$(ARCH).tar $(DESTDIR)/usr/lib/embassy/system-images/utils.tar
|
||||
cp system-images/binfmt/docker-images/$(ARCH).tar $(DESTDIR)/usr/lib/embassy/system-images/binfmt.tar
|
||||
$(call mkdir,$(DESTDIR)/usr/lib/embassy/system-images)
|
||||
$(call cp,system-images/compat/docker-images/aarch64.tar,$(DESTDIR)/usr/lib/embassy/system-images/compat.tar)
|
||||
$(call cp,system-images/utils/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/embassy/system-images/utils.tar)
|
||||
$(call cp,system-images/binfmt/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/embassy/system-images/binfmt.tar)
|
||||
|
||||
mkdir -p $(DESTDIR)/var/www/html
|
||||
cp -r frontend/dist/diagnostic-ui $(DESTDIR)/var/www/html/diagnostic
|
||||
cp -r frontend/dist/setup-wizard $(DESTDIR)/var/www/html/setup
|
||||
cp -r frontend/dist/install-wizard $(DESTDIR)/var/www/html/install
|
||||
cp -r frontend/dist/ui $(DESTDIR)/var/www/html/main
|
||||
cp index.html $(DESTDIR)/var/www/html/
|
||||
$(call mkdir,$(DESTDIR)/var/www/html)
|
||||
$(call cp,frontend/dist/diagnostic-ui,$(DESTDIR)/var/www/html/diagnostic)
|
||||
$(call cp,frontend/dist/setup-wizard,$(DESTDIR)/var/www/html/setup)
|
||||
$(call cp,frontend/dist/install-wizard,$(DESTDIR)/var/www/html/install)
|
||||
$(call cp,frontend/dist/ui,$(DESTDIR)/var/www/html/main)
|
||||
$(call cp,index.html,$(DESTDIR)/var/www/html/index.html)
|
||||
|
||||
update-overlay:
|
||||
@echo "\033[33m!!! THIS WILL ONLY REFLASH YOUR DEVICE IN MEMORY !!!\033[0m"
|
||||
@echo "\033[33mALL CHANGES WILL BE REVERTED IF YOU RESTART THE DEVICE\033[0m"
|
||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||
@if [ "`ssh $(REMOTE) 'cat /usr/lib/embassy/VERSION.txt'`" != "`cat ./VERSION.txt`" ]; then >&2 echo "Embassy requires migrations: update-overlay is unavailable." && false; fi
|
||||
@if ssh $(REMOTE) "pidof embassy-init"; then >&2 echo "Embassy in INIT: update-overlay is unavailable." && false; fi
|
||||
ssh $(REMOTE) "sudo systemctl stop embassyd"
|
||||
$(MAKE) install REMOTE=$(REMOTE) OS_ARCH=$(OS_ARCH)
|
||||
ssh $(REMOTE) "sudo systemctl start embassyd"
|
||||
|
||||
update:
|
||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||
ssh $(REMOTE) "sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/"
|
||||
$(MAKE) install REMOTE=$(REMOTE) DESTDIR=/media/embassy/next OS_ARCH=$(OS_ARCH)
|
||||
ssh $(REMOTE) "sudo touch /media/embassy/config/upgrade && sudo sync && sudo reboot"
|
||||
|
||||
emulate-reflash:
|
||||
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
|
||||
ssh $(REMOTE) "sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/"
|
||||
$(MAKE) install REMOTE=$(REMOTE) DESTDIR=/media/embassy/next OS_ARCH=$(OS_ARCH)
|
||||
ssh $(REMOTE) "sudo touch /media/embassy/config/upgrade && sudo rm -f /media/embassy/config/disk.guid && sudo sync && sudo reboot"
|
||||
|
||||
system-images/compat/docker-images/aarch64.tar: $(COMPAT_SRC)
|
||||
cd system-images/compat && make
|
||||
|
||||
41
backend/Cargo.lock
generated
41
backend/Cargo.lock
generated
@@ -485,6 +485,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
@@ -770,6 +776,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
dependencies = [
|
||||
"build_const",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.1"
|
||||
@@ -1369,6 +1384,7 @@ dependencies = [
|
||||
"fd-lock-rs",
|
||||
"futures",
|
||||
"git-version",
|
||||
"gpt",
|
||||
"helpers",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
@@ -1439,7 +1455,7 @@ dependencies = [
|
||||
"trust-dns-server",
|
||||
"typed-builder",
|
||||
"url",
|
||||
"uuid",
|
||||
"uuid 1.3.0",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -1882,6 +1898,18 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "gpt"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd7365d734a70ac5dd7be791b0c96083852188df015b8c665bb2dadb108a743"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc 1.8.1",
|
||||
"log",
|
||||
"uuid 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.1"
|
||||
@@ -4503,7 +4531,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crc 3.0.1",
|
||||
"crossbeam-queue",
|
||||
"dirs",
|
||||
"dotenvy",
|
||||
@@ -5757,6 +5785,15 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.3.0"
|
||||
|
||||
@@ -81,6 +81,7 @@ emver = { version = "0.1.7", git = "https://github.com/Start9Labs/emver-rs.git",
|
||||
fd-lock-rs = "0.1.4"
|
||||
futures = "0.3.21"
|
||||
git-version = "0.3.5"
|
||||
gpt = "3.0.0"
|
||||
helpers = { path = "../libs/helpers" }
|
||||
embassy_container_init = { path = "../libs/embassy_container_init" }
|
||||
hex = "0.4.3"
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde::Deserialize;
|
||||
use tokio::sync::broadcast::Sender;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::net::net_utils::find_eth_iface;
|
||||
use crate::net::utils::find_eth_iface;
|
||||
use crate::util::config::load_config_from_paths;
|
||||
use crate::Error;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::account::AccountInfo;
|
||||
use crate::config::spec::{PackagePointerSpec, SystemPointerSpec};
|
||||
use crate::install::progress::InstallProgress;
|
||||
use crate::net::interface::InterfaceId;
|
||||
use crate::net::net_utils::{get_iface_ipv4_addr, get_iface_ipv6_addr};
|
||||
use crate::net::utils::{get_iface_ipv4_addr, get_iface_ipv6_addr};
|
||||
use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId};
|
||||
use crate::status::health_check::HealthCheckId;
|
||||
use crate::status::Status;
|
||||
|
||||
@@ -18,15 +18,21 @@ pub mod util;
|
||||
pub const BOOT_RW_PATH: &str = "/media/boot-rw";
|
||||
pub const REPAIR_DISK_PATH: &str = "/media/embassy/config/repair-disk";
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct OsPartitionInfo {
|
||||
pub efi: Option<PathBuf>,
|
||||
pub boot: PathBuf,
|
||||
pub root: PathBuf,
|
||||
}
|
||||
impl OsPartitionInfo {
|
||||
pub fn contains(&self, logicalname: impl AsRef<Path>) -> bool {
|
||||
&*self.boot == logicalname.as_ref() || &*self.root == logicalname.as_ref()
|
||||
self.efi
|
||||
.as_ref()
|
||||
.map(|p| p == logicalname.as_ref())
|
||||
.unwrap_or(false)
|
||||
|| &*self.boot == logicalname.as_ref()
|
||||
|| &*self.root == logicalname.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
40
backend/src/disk/mount/filesystem/efivarfs.rs
Normal file
40
backend/src/disk/mount/filesystem/efivarfs.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::Path;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use digest::generic_array::GenericArray;
|
||||
use digest::{Digest, OutputSizeUser};
|
||||
use sha2::Sha256;
|
||||
|
||||
use super::{FileSystem, MountType, ReadOnly};
|
||||
use crate::util::Invoke;
|
||||
use crate::{Error, ResultExt};
|
||||
|
||||
pub struct EfiVarFs;
|
||||
#[async_trait]
|
||||
impl FileSystem for EfiVarFs {
|
||||
async fn mount<P: AsRef<Path> + Send + Sync>(
|
||||
&self,
|
||||
mountpoint: P,
|
||||
mount_type: MountType,
|
||||
) -> Result<(), Error> {
|
||||
tokio::fs::create_dir_all(mountpoint.as_ref()).await?;
|
||||
let mut cmd = tokio::process::Command::new("mount");
|
||||
cmd.arg("-t")
|
||||
.arg("efivarfs")
|
||||
.arg("efivarfs")
|
||||
.arg(mountpoint.as_ref());
|
||||
if mount_type == ReadOnly {
|
||||
cmd.arg("-o").arg("ro");
|
||||
}
|
||||
cmd.invoke(crate::ErrorKind::Filesystem).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn source_hash(
|
||||
&self,
|
||||
) -> Result<GenericArray<u8, <Sha256 as OutputSizeUser>::OutputSize>, Error> {
|
||||
let mut sha = Sha256::new();
|
||||
sha.update("EfiVarFs");
|
||||
Ok(sha.finalize())
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ pub mod bind;
|
||||
pub mod block_dev;
|
||||
pub mod cifs;
|
||||
pub mod ecryptfs;
|
||||
pub mod efivarfs;
|
||||
pub mod httpdirfs;
|
||||
pub mod label;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use models::ResultExt;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -36,9 +37,21 @@ impl MountGuard {
|
||||
mounted: true,
|
||||
})
|
||||
}
|
||||
pub async fn unmount(mut self) -> Result<(), Error> {
|
||||
pub async fn unmount(mut self, delete_mountpoint: bool) -> Result<(), Error> {
|
||||
if self.mounted {
|
||||
unmount(&self.mountpoint).await?;
|
||||
if delete_mountpoint {
|
||||
match tokio::fs::remove_dir(&self.mountpoint).await {
|
||||
Err(e) if e.raw_os_error() == Some(39) => Ok(()), // directory not empty
|
||||
a => a,
|
||||
}
|
||||
.with_ctx(|_| {
|
||||
(
|
||||
crate::ErrorKind::Filesystem,
|
||||
format!("rm {}", self.mountpoint.display()),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
self.mounted = false;
|
||||
}
|
||||
Ok(())
|
||||
@@ -60,7 +73,7 @@ impl Drop for MountGuard {
|
||||
#[async_trait::async_trait]
|
||||
impl GenericMountGuard for MountGuard {
|
||||
async fn unmount(mut self) -> Result<(), Error> {
|
||||
MountGuard::unmount(self).await
|
||||
MountGuard::unmount(self, false).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +124,7 @@ impl TmpMountGuard {
|
||||
}
|
||||
pub async fn unmount(self) -> Result<(), Error> {
|
||||
if let Ok(guard) = Arc::try_unwrap(self.guard) {
|
||||
guard.unmount().await?;
|
||||
guard.unmount(true).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -48,15 +48,5 @@ pub async fn unmount<P: AsRef<Path>>(mountpoint: P) -> Result<(), Error> {
|
||||
.arg(mountpoint.as_ref())
|
||||
.invoke(crate::ErrorKind::Filesystem)
|
||||
.await?;
|
||||
match tokio::fs::remove_dir(mountpoint.as_ref()).await {
|
||||
Err(e) if e.raw_os_error() == Some(39) => Ok(()), // directory not empty
|
||||
a => a,
|
||||
}
|
||||
.with_ctx(|_| {
|
||||
(
|
||||
crate::ErrorKind::Filesystem,
|
||||
format!("rm {}", mountpoint.as_ref().display()),
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -23,10 +23,18 @@ use crate::util::serde::IoFormat;
|
||||
use crate::util::{Invoke, Version};
|
||||
use crate::{Error, ResultExt as _};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum PartitionTable {
|
||||
Mbr,
|
||||
Gpt,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct DiskInfo {
|
||||
pub logicalname: PathBuf,
|
||||
pub partition_table: Option<PartitionTable>,
|
||||
pub vendor: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub partitions: Vec<PartitionInfo>,
|
||||
@@ -61,6 +69,24 @@ lazy_static::lazy_static! {
|
||||
static ref PARTITION_REGEX: Regex = Regex::new("-part[0-9]+$").unwrap();
|
||||
}
|
||||
|
||||
#[instrument(skip(path))]
|
||||
pub async fn get_partition_table<P: AsRef<Path>>(path: P) -> Result<Option<PartitionTable>, Error> {
|
||||
Ok(String::from_utf8(
|
||||
Command::new("fdisk")
|
||||
.arg("-l")
|
||||
.arg(path.as_ref())
|
||||
.invoke(crate::ErrorKind::BlockDevice)
|
||||
.await?,
|
||||
)?
|
||||
.lines()
|
||||
.find_map(|l| l.strip_prefix("Disklabel type:"))
|
||||
.and_then(|t| match t.trim() {
|
||||
"dos" => Some(PartitionTable::Mbr),
|
||||
"gpt" => Some(PartitionTable::Gpt),
|
||||
_ => None,
|
||||
}))
|
||||
}
|
||||
|
||||
#[instrument(skip(path))]
|
||||
pub async fn get_vendor<P: AsRef<Path>>(path: P) -> Result<Option<String>, Error> {
|
||||
let vendor = tokio::fs::read_to_string(
|
||||
@@ -328,6 +354,16 @@ pub async fn list(os: &OsPartitionInfo) -> Result<Vec<DiskInfo>, Error> {
|
||||
}
|
||||
|
||||
async fn disk_info(disk: PathBuf) -> DiskInfo {
|
||||
let partition_table = get_partition_table(&disk)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!(
|
||||
"Could not get partition table of {}: {}",
|
||||
disk.display(),
|
||||
e.source
|
||||
)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let vendor = get_vendor(&disk)
|
||||
.await
|
||||
.map_err(|e| tracing::warn!("Could not get vendor of {}: {}", disk.display(), e.source))
|
||||
@@ -342,6 +378,7 @@ async fn disk_info(disk: PathBuf) -> DiskInfo {
|
||||
.unwrap_or_default();
|
||||
DiskInfo {
|
||||
logicalname: disk,
|
||||
partition_table,
|
||||
vendor,
|
||||
model,
|
||||
partitions: Vec::new(),
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
{boot} /boot vfat defaults 0 2
|
||||
{root} / ext4 defaults 0 1
|
||||
@@ -232,7 +232,12 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
|
||||
format!("write {}", LOCAL_AUTH_COOKIE_PATH),
|
||||
)
|
||||
})?;
|
||||
tokio::fs::set_permissions(LOCAL_AUTH_COOKIE_PATH, Permissions::from_mode(046)).await?;
|
||||
tokio::fs::set_permissions(LOCAL_AUTH_COOKIE_PATH, Permissions::from_mode(0o046)).await?;
|
||||
Command::new("chown")
|
||||
.arg("root:embassy")
|
||||
.arg(LOCAL_AUTH_COOKIE_PATH)
|
||||
.invoke(crate::ErrorKind::Filesystem)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let secret_store = cfg.secret_store().await?;
|
||||
|
||||
@@ -106,7 +106,7 @@ impl HasValidSession {
|
||||
}
|
||||
|
||||
pub async fn from_local(local: &Cookie<'_>) -> Result<Self, Error> {
|
||||
let token = tokio::fs::read_to_string("/run/embassy/rpc.authcookie").await?;
|
||||
let token = tokio::fs::read_to_string(LOCAL_AUTH_COOKIE_PATH).await?;
|
||||
if local.get_value() == &*token {
|
||||
Ok(Self(()))
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@ use tokio::sync::RwLock;
|
||||
|
||||
use crate::context::RpcContext;
|
||||
use crate::db::model::IpInfo;
|
||||
use crate::net::net_utils::{iface_is_physical, list_interfaces};
|
||||
use crate::net::utils::{iface_is_physical, list_interfaces};
|
||||
use crate::util::display_none;
|
||||
use crate::Error;
|
||||
|
||||
|
||||
@@ -13,11 +13,11 @@ pub mod keys;
|
||||
#[cfg(feature = "avahi")]
|
||||
pub mod mdns;
|
||||
pub mod net_controller;
|
||||
pub mod net_utils;
|
||||
pub mod ssl;
|
||||
pub mod static_server;
|
||||
pub mod tor;
|
||||
pub mod vhost_controller;
|
||||
pub mod utils;
|
||||
pub mod vhost;
|
||||
pub mod web_server;
|
||||
pub mod wifi;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::net::keys::Key;
|
||||
use crate::net::mdns::MdnsController;
|
||||
use crate::net::ssl::{export_cert, SslManager};
|
||||
use crate::net::tor::TorController;
|
||||
use crate::net::vhost_controller::VHostController;
|
||||
use crate::net::vhost::VHostController;
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::volume::cert_dir;
|
||||
use crate::{Error, HOST_IP};
|
||||
|
||||
@@ -16,8 +16,8 @@ use tokio_rustls::rustls::{RootCertStore, ServerConfig};
|
||||
use tokio_rustls::{LazyConfigAcceptor, TlsConnector};
|
||||
|
||||
use crate::net::keys::Key;
|
||||
use crate::net::net_utils::SingleAccept;
|
||||
use crate::net::ssl::SslManager;
|
||||
use crate::net::utils::SingleAccept;
|
||||
use crate::util::io::BackTrackingReader;
|
||||
use crate::Error;
|
||||
|
||||
3
backend/src/os_install/fstab.template
Normal file
3
backend/src/os_install/fstab.template
Normal file
@@ -0,0 +1,3 @@
|
||||
{boot} /boot vfat umask=0077 0 2
|
||||
{efi} /boot/efi vfat umask=0077 0 1
|
||||
{root} / ext4 defaults 0 1
|
||||
122
backend/src/os_install/gpt.rs
Normal file
122
backend/src/os_install/gpt.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use color_eyre::eyre::eyre;
|
||||
use gpt::disk::LogicalBlockSize;
|
||||
use gpt::GptConfig;
|
||||
|
||||
use crate::disk::util::DiskInfo;
|
||||
use crate::disk::OsPartitionInfo;
|
||||
use crate::os_install::partition_for;
|
||||
use crate::Error;
|
||||
|
||||
pub async fn partition(disk: &DiskInfo, overwrite: bool) -> Result<OsPartitionInfo, Error> {
|
||||
{
|
||||
let disk = disk.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let mut device = Box::new(
|
||||
std::fs::File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&disk.logicalname)?,
|
||||
);
|
||||
let (mut gpt, guid_part) = if overwrite {
|
||||
let mbr = gpt::mbr::ProtectiveMBR::with_lb_size(
|
||||
u32::try_from((disk.capacity / 512) - 1).unwrap_or(0xFF_FF_FF_FF),
|
||||
);
|
||||
mbr.overwrite_lba0(&mut device)?;
|
||||
(
|
||||
GptConfig::new()
|
||||
.writable(true)
|
||||
.initialized(false)
|
||||
.logical_block_size(LogicalBlockSize::Lb512)
|
||||
.create_from_device(device, None)?,
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
let gpt = GptConfig::new()
|
||||
.writable(true)
|
||||
.initialized(true)
|
||||
.logical_block_size(LogicalBlockSize::Lb512)
|
||||
.open_from_device(device)?;
|
||||
let mut guid_part = None;
|
||||
for (idx, part_info) in disk
|
||||
.partitions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, x)| (idx + 1, x))
|
||||
{
|
||||
if let Some(entry) = gpt.partitions().get(&(idx as u32)) {
|
||||
if entry.first_lba >= 33556480 {
|
||||
if idx < 3 {
|
||||
guid_part = Some(entry.clone())
|
||||
}
|
||||
break;
|
||||
}
|
||||
if part_info.guid.is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("Not enough space before embassy data"),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
(gpt, guid_part)
|
||||
};
|
||||
|
||||
gpt.update_partitions(Default::default())?;
|
||||
|
||||
gpt.add_partition("efi", 100 * 1024 * 1024, gpt::partition_types::EFI, 0, None)?;
|
||||
gpt.add_partition(
|
||||
"boot",
|
||||
1024 * 1024 * 1024,
|
||||
gpt::partition_types::LINUX_FS,
|
||||
0,
|
||||
None,
|
||||
)?;
|
||||
gpt.add_partition(
|
||||
"root",
|
||||
15 * 1024 * 1024 * 1024,
|
||||
match *crate::ARCH {
|
||||
"x86_64" => gpt::partition_types::LINUX_ROOT_X64,
|
||||
"aarch64" => gpt::partition_types::LINUX_ROOT_ARM_64,
|
||||
_ => gpt::partition_types::LINUX_FS,
|
||||
},
|
||||
0,
|
||||
None,
|
||||
)?;
|
||||
|
||||
if overwrite {
|
||||
gpt.add_partition(
|
||||
"data",
|
||||
gpt.find_free_sectors()
|
||||
.iter()
|
||||
.map(|(_, size)| *size * u64::from(*gpt.logical_block_size()))
|
||||
.max()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("No free space left on device"),
|
||||
crate::ErrorKind::BlockDevice,
|
||||
)
|
||||
})?,
|
||||
gpt::partition_types::LINUX_LVM,
|
||||
0,
|
||||
None,
|
||||
)?;
|
||||
} else if let Some(guid_part) = guid_part {
|
||||
let mut parts = gpt.partitions().clone();
|
||||
parts.insert(gpt.find_next_partition_id(), guid_part);
|
||||
gpt.update_partitions(parts)?;
|
||||
}
|
||||
|
||||
gpt.write()?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
}
|
||||
|
||||
Ok(OsPartitionInfo {
|
||||
efi: Some(partition_for(&disk.logicalname, 1)),
|
||||
boot: partition_for(&disk.logicalname, 2),
|
||||
root: partition_for(&disk.logicalname, 3),
|
||||
})
|
||||
}
|
||||
91
backend/src/os_install/mbr.rs
Normal file
91
backend/src/os_install/mbr.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use color_eyre::eyre::eyre;
|
||||
use mbrman::{MBRPartitionEntry, CHS, MBR};
|
||||
|
||||
use crate::disk::util::DiskInfo;
|
||||
use crate::disk::OsPartitionInfo;
|
||||
use crate::os_install::partition_for;
|
||||
use crate::Error;
|
||||
|
||||
pub async fn partition(disk: &DiskInfo, overwrite: bool) -> Result<OsPartitionInfo, Error> {
|
||||
{
|
||||
let sectors = (disk.capacity / 512) as u32;
|
||||
let disk = disk.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let mut file = std::fs::File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&disk.logicalname)?;
|
||||
let (mut mbr, guid_part) = if overwrite {
|
||||
(MBR::new_from(&mut file, 512, rand::random())?, None)
|
||||
} else {
|
||||
let mut mbr = MBR::read_from(&mut file, 512)?;
|
||||
let mut guid_part = None;
|
||||
for (idx, part_info) in disk
|
||||
.partitions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, x)| (idx + 1, x))
|
||||
{
|
||||
if let Some(entry) = mbr.get_mut(idx) {
|
||||
if entry.starting_lba >= 33556480 {
|
||||
if idx < 3 {
|
||||
guid_part =
|
||||
Some(std::mem::replace(entry, MBRPartitionEntry::empty()))
|
||||
}
|
||||
break;
|
||||
}
|
||||
if part_info.guid.is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("Not enough space before embassy data"),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
*entry = MBRPartitionEntry::empty();
|
||||
}
|
||||
}
|
||||
(mbr, guid_part)
|
||||
};
|
||||
|
||||
mbr[1] = MBRPartitionEntry {
|
||||
boot: 0x80,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x0b,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 2048,
|
||||
sectors: 2099200 - 2048,
|
||||
};
|
||||
mbr[2] = MBRPartitionEntry {
|
||||
boot: 0,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x83,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 2099200,
|
||||
sectors: 33556480 - 2099200,
|
||||
};
|
||||
|
||||
if overwrite {
|
||||
mbr[3] = MBRPartitionEntry {
|
||||
boot: 0,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x8e,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 33556480,
|
||||
sectors: sectors - 33556480,
|
||||
}
|
||||
} else if let Some(guid_part) = guid_part {
|
||||
mbr[3] = guid_part;
|
||||
}
|
||||
mbr.write_into(&mut file)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
}
|
||||
|
||||
Ok(OsPartitionInfo {
|
||||
efi: None,
|
||||
boot: partition_for(&disk.logicalname, 1),
|
||||
root: partition_for(&disk.logicalname, 2),
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use color_eyre::eyre::eyre;
|
||||
use mbrman::{MBRPartitionEntry, CHS, MBR};
|
||||
use models::Error;
|
||||
use rpc_toolkit::command;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -10,13 +9,18 @@ use tokio::process::Command;
|
||||
use crate::context::InstallContext;
|
||||
use crate::disk::mount::filesystem::bind::Bind;
|
||||
use crate::disk::mount::filesystem::block_dev::BlockDev;
|
||||
use crate::disk::mount::filesystem::efivarfs::EfiVarFs;
|
||||
use crate::disk::mount::filesystem::ReadWrite;
|
||||
use crate::disk::mount::guard::{MountGuard, TmpMountGuard};
|
||||
use crate::disk::util::DiskInfo;
|
||||
use crate::disk::util::{DiskInfo, PartitionTable};
|
||||
use crate::disk::OsPartitionInfo;
|
||||
use crate::net::net_utils::{find_eth_iface, find_wifi_iface};
|
||||
use crate::net::utils::{find_eth_iface, find_wifi_iface};
|
||||
use crate::util::serde::IoFormat;
|
||||
use crate::util::{display_none, Invoke};
|
||||
use crate::ARCH;
|
||||
|
||||
mod gpt;
|
||||
mod mbr;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
@@ -87,12 +91,30 @@ pub fn partition_for(disk: impl AsRef<Path>, idx: usize) -> PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
async fn partition(disk: &mut DiskInfo, overwrite: bool) -> Result<OsPartitionInfo, Error> {
|
||||
let partition_type = match (overwrite, disk.partition_table) {
|
||||
(true, _) | (_, None) => {
|
||||
if tokio::fs::metadata("/sys/firmware/efi").await.is_ok() {
|
||||
PartitionTable::Gpt
|
||||
} else {
|
||||
PartitionTable::Mbr
|
||||
}
|
||||
}
|
||||
(_, Some(t)) => t,
|
||||
};
|
||||
disk.partition_table = Some(partition_type);
|
||||
match partition_type {
|
||||
PartitionTable::Gpt => gpt::partition(disk, overwrite).await,
|
||||
PartitionTable::Mbr => mbr::partition(disk, overwrite).await,
|
||||
}
|
||||
}
|
||||
|
||||
#[command(display(display_none))]
|
||||
pub async fn execute(
|
||||
#[arg] logicalname: PathBuf,
|
||||
#[arg(short = 'o')] mut overwrite: bool,
|
||||
) -> Result<(), Error> {
|
||||
let disk = crate::disk::util::list(&Default::default())
|
||||
let mut disk = crate::disk::util::list(&Default::default())
|
||||
.await?
|
||||
.into_iter()
|
||||
.find(|d| &d.logicalname == &logicalname)
|
||||
@@ -106,110 +128,60 @@ pub async fn execute(
|
||||
let wifi_iface = find_wifi_iface().await?;
|
||||
|
||||
overwrite |= disk.guid.is_none() && disk.partitions.iter().all(|p| p.guid.is_none());
|
||||
let sectors = (disk.capacity / 512) as u32;
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let mut file = std::fs::File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(&logicalname)?;
|
||||
let (mut mbr, guid_part) = if overwrite {
|
||||
(MBR::new_from(&mut file, 512, rand::random())?, None)
|
||||
} else {
|
||||
let mut mbr = MBR::read_from(&mut file, 512)?;
|
||||
let mut guid_part = None;
|
||||
for (idx, part_info) in disk
|
||||
.partitions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, x)| (idx + 1, x))
|
||||
{
|
||||
if let Some(entry) = mbr.get_mut(idx) {
|
||||
if entry.starting_lba >= 33556480 {
|
||||
if idx < 3 {
|
||||
guid_part = Some(std::mem::replace(entry, MBRPartitionEntry::empty()))
|
||||
}
|
||||
break;
|
||||
}
|
||||
if part_info.guid.is_some() {
|
||||
return Err(Error::new(
|
||||
eyre!("Not enough space before embassy data"),
|
||||
crate::ErrorKind::InvalidRequest,
|
||||
));
|
||||
}
|
||||
*entry = MBRPartitionEntry::empty();
|
||||
}
|
||||
}
|
||||
(mbr, guid_part)
|
||||
};
|
||||
|
||||
mbr[1] = MBRPartitionEntry {
|
||||
boot: 0x80,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x0b,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 2048,
|
||||
sectors: 2099200 - 2048,
|
||||
};
|
||||
mbr[2] = MBRPartitionEntry {
|
||||
boot: 0,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x83,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 2099200,
|
||||
sectors: 33556480 - 2099200,
|
||||
};
|
||||
|
||||
if overwrite {
|
||||
mbr[3] = MBRPartitionEntry {
|
||||
boot: 0,
|
||||
first_chs: CHS::empty(),
|
||||
sys: 0x8e,
|
||||
last_chs: CHS::empty(),
|
||||
starting_lba: 33556480,
|
||||
sectors: sectors - 33556480,
|
||||
}
|
||||
} else if let Some(guid_part) = guid_part {
|
||||
mbr[3] = guid_part;
|
||||
}
|
||||
mbr.write_into(&mut file)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
|
||||
let boot_part = partition_for(&disk.logicalname, 1);
|
||||
let root_part = partition_for(&disk.logicalname, 2);
|
||||
let part_info = partition(&mut disk, overwrite).await?;
|
||||
|
||||
if let Some(efi) = &part_info.efi {
|
||||
Command::new("mkfs.vfat")
|
||||
.arg(&boot_part)
|
||||
.arg(efi)
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
Command::new("fatlabel")
|
||||
.arg(&boot_part)
|
||||
.arg(efi)
|
||||
.arg("efi")
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Command::new("mkfs.vfat")
|
||||
.arg(&part_info.boot)
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
Command::new("fatlabel")
|
||||
.arg(&part_info.boot)
|
||||
.arg("boot")
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
|
||||
Command::new("mkfs.ext4")
|
||||
.arg(&root_part)
|
||||
.arg(&part_info.root)
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
Command::new("e2label")
|
||||
.arg(&root_part)
|
||||
.arg(&part_info.root)
|
||||
.arg("rootfs")
|
||||
.invoke(crate::ErrorKind::DiskManagement)
|
||||
.await?;
|
||||
|
||||
let rootfs = TmpMountGuard::mount(&BlockDev::new(&root_part), ReadWrite).await?;
|
||||
let rootfs = TmpMountGuard::mount(&BlockDev::new(&part_info.root), ReadWrite).await?;
|
||||
tokio::fs::create_dir(rootfs.as_ref().join("config")).await?;
|
||||
tokio::fs::create_dir(rootfs.as_ref().join("next")).await?;
|
||||
let current = rootfs.as_ref().join("current");
|
||||
tokio::fs::create_dir(¤t).await?;
|
||||
|
||||
tokio::fs::create_dir(current.join("boot")).await?;
|
||||
let boot =
|
||||
MountGuard::mount(&BlockDev::new(&boot_part), current.join("boot"), ReadWrite).await?;
|
||||
let boot = MountGuard::mount(
|
||||
&BlockDev::new(&part_info.boot),
|
||||
current.join("boot"),
|
||||
ReadWrite,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let efi = if let Some(efi) = &part_info.efi {
|
||||
Some(MountGuard::mount(&BlockDev::new(efi), current.join("boot/efi"), ReadWrite).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Command::new("unsquashfs")
|
||||
.arg("-n")
|
||||
@@ -223,10 +195,7 @@ pub async fn execute(
|
||||
tokio::fs::write(
|
||||
rootfs.as_ref().join("config/config.yaml"),
|
||||
IoFormat::Yaml.to_vec(&PostInstallConfig {
|
||||
os_partitions: OsPartitionInfo {
|
||||
boot: boot_part.clone(),
|
||||
root: root_part.clone(),
|
||||
},
|
||||
os_partitions: part_info.clone(),
|
||||
ethernet_interface: eth_iface,
|
||||
wifi_interface: wifi_iface,
|
||||
})?,
|
||||
@@ -237,8 +206,13 @@ pub async fn execute(
|
||||
current.join("etc/fstab"),
|
||||
format!(
|
||||
include_str!("fstab.template"),
|
||||
boot = boot_part.display(),
|
||||
root = root_part.display()
|
||||
boot = part_info.boot.display(),
|
||||
efi = part_info
|
||||
.efi
|
||||
.as_ref()
|
||||
.map(|p| p.display().to_string())
|
||||
.unwrap_or_else(|| "# N/A".to_owned()),
|
||||
root = part_info.root.display(),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
@@ -257,26 +231,52 @@ pub async fn execute(
|
||||
.await?;
|
||||
|
||||
let dev = MountGuard::mount(&Bind::new("/dev"), current.join("dev"), ReadWrite).await?;
|
||||
let sys = MountGuard::mount(&Bind::new("/sys"), current.join("sys"), ReadWrite).await?;
|
||||
let proc = MountGuard::mount(&Bind::new("/proc"), current.join("proc"), ReadWrite).await?;
|
||||
let sys = MountGuard::mount(&Bind::new("/sys"), current.join("sys"), ReadWrite).await?;
|
||||
let efivarfs = if let Some(efi) = &part_info.efi {
|
||||
Some(
|
||||
MountGuard::mount(
|
||||
&EfiVarFs,
|
||||
current.join("sys/firmware/efi/efivars"),
|
||||
ReadWrite,
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Command::new("chroot")
|
||||
.arg(¤t)
|
||||
.arg("update-grub")
|
||||
.invoke(crate::ErrorKind::Grub)
|
||||
.await?;
|
||||
Command::new("chroot")
|
||||
.arg(¤t)
|
||||
.arg("grub-install")
|
||||
.arg("--target=i386-pc")
|
||||
let mut install = Command::new("chroot");
|
||||
install.arg(¤t).arg("grub-install");
|
||||
if part_info.efi.is_none() {
|
||||
install.arg("--target=i386-pc");
|
||||
} else {
|
||||
match *ARCH {
|
||||
"x86_64" => install.arg("--target=x86_64-efi"),
|
||||
"aarch64" => install.arg("--target=arm64-efi"),
|
||||
_ => &mut install,
|
||||
};
|
||||
}
|
||||
install
|
||||
.arg(&disk.logicalname)
|
||||
.invoke(crate::ErrorKind::Grub)
|
||||
.await?;
|
||||
|
||||
dev.unmount().await?;
|
||||
sys.unmount().await?;
|
||||
proc.unmount().await?;
|
||||
boot.unmount().await?;
|
||||
dev.unmount(false).await?;
|
||||
if let Some(efivarfs) = efivarfs {
|
||||
efivarfs.unmount(false).await?;
|
||||
}
|
||||
sys.unmount(false).await?;
|
||||
proc.unmount(false).await?;
|
||||
if let Some(efi) = efi {
|
||||
efi.unmount(false).await?;
|
||||
}
|
||||
boot.unmount(false).await?;
|
||||
rootfs.unmount().await?;
|
||||
|
||||
Ok(())
|
||||
@@ -325,10 +325,10 @@ async fn sync_boot() -> Result<(), Error> {
|
||||
.arg("update-grub")
|
||||
.invoke(ErrorKind::MigrationFailed)
|
||||
.await?;
|
||||
boot_mnt.unmount().await?;
|
||||
proc_mnt.unmount().await?;
|
||||
sys_mnt.unmount().await?;
|
||||
dev_mnt.unmount().await?;
|
||||
boot_mnt.unmount(false).await?;
|
||||
proc_mnt.unmount(false).await?;
|
||||
sys_mnt.unmount(false).await?;
|
||||
dev_mnt.unmount(false).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ function partition_for () {
|
||||
fi
|
||||
}
|
||||
|
||||
TARGET_NAME=embassyos-raspi.img
|
||||
TARGET_NAME=embassyos-raspi-uninit.img
|
||||
TARGET_SIZE=2400000000
|
||||
|
||||
cp raspios.img $TARGET_NAME
|
||||
|
||||
41
system-images/compat/Cargo.lock
generated
41
system-images/compat/Cargo.lock
generated
@@ -426,6 +426,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
@@ -706,6 +712,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
dependencies = [
|
||||
"build_const",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.0"
|
||||
@@ -1185,6 +1200,7 @@ dependencies = [
|
||||
"fd-lock-rs",
|
||||
"futures",
|
||||
"git-version",
|
||||
"gpt",
|
||||
"helpers",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
@@ -1254,7 +1270,7 @@ dependencies = [
|
||||
"trust-dns-server",
|
||||
"typed-builder",
|
||||
"url",
|
||||
"uuid",
|
||||
"uuid 1.2.2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -1666,6 +1682,18 @@ dependencies = [
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpt"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd7365d734a70ac5dd7be791b0c96083852188df015b8c665bb2dadb108a743"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc 1.8.1",
|
||||
"log",
|
||||
"uuid 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.1"
|
||||
@@ -4076,7 +4104,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crc 3.0.0",
|
||||
"crossbeam-queue",
|
||||
"dirs",
|
||||
"dotenvy",
|
||||
@@ -4897,6 +4925,15 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.2.2"
|
||||
|
||||
Reference in New Issue
Block a user