Compare commits
21 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c7f825858c | ||
|
01cab85f6b | ||
|
43ef704a32 | ||
|
79a4768ae7 | ||
|
4c3fb48ac7 | ||
|
768af6db31 | ||
|
97a5127a59 | ||
|
a119d6ac19 | ||
|
c0f74a254a | ||
|
298e7c56da | ||
|
fe1435b27f | ||
|
8258fb93e5 | ||
|
92c4c23044 | ||
|
69450716fb | ||
|
2d218d535f | ||
|
c997576dce | ||
|
cf5deedbb2 | ||
|
29e8665223 | ||
|
6bbd36c9ea | ||
|
5a57ab02e8 | ||
|
5636e187aa |
33
Makefile
33
Makefile
|
@ -3,41 +3,30 @@ NAME = lon-tool
|
||||||
SRC ?= main.go
|
SRC ?= main.go
|
||||||
BIN_DIR ?= ./bin
|
BIN_DIR ?= ./bin
|
||||||
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
|
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
|
||||||
GOFLAGS ?= -ldflags="-s -w -X lon-tool/cmd.version=$(GIT_VERSION)"
|
GOFLAGS ?= -ldflags="-s -w -X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$(GIT_VERSION)"
|
||||||
WINDOWS_GOFLAGS ?= -ldflags="-extldflags=-static -s -w -X lon-tool/cmd.version=$(GIT_VERSION)"
|
WINDOWS_GOFLAGS ?= -ldflags="-extldflags=-static -s -w -X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$(GIT_VERSION)"
|
||||||
|
|
||||||
# macOS settings
|
|
||||||
MACOS_BIN = $(BIN_DIR)/$(NAME)_mac_amd64
|
|
||||||
MACOS_CC = x86_64-apple-darwin23-gcc-14
|
|
||||||
MACOS_CXX = x86_64-apple-darwin23-g++-14
|
|
||||||
|
|
||||||
# Windows settings
|
# Windows settings
|
||||||
WINDOWS_BIN = $(BIN_DIR)/$(NAME)_win_amd64.exe
|
WINDOWS_BIN = $(BIN_DIR)/$(NAME)_win_amd64.exe
|
||||||
WINDOWS_CC = x86_64-w64-mingw32-gcc
|
WINDOWS_CC = x86_64-w64-mingw32-gcc
|
||||||
WINDOWS_CXX = x86_64-w64-mingw32-g++
|
WINDOWS_CXX = x86_64-w64-mingw32-g++
|
||||||
WINDOWS_PKG_CONFIG_PATH = /usr/local/x86_64-w64-mingw32/lib/pkgconfig
|
WINDOWS_PKG_CONFIG_PATH = /usr/x86_64-w64-mingw32/lib/pkgconfig
|
||||||
WINDOWS_CGO_CFLAGS = -I/usr/local/x86_64-w64-mingw32/include
|
WINDOWS_CGO_CFLAGS = -I/usr/x86_64-w64-mingw32/include
|
||||||
WINDOWS_CGO_LDFLAGS = -L/usr/local/x86_64-w64-mingw32/lib
|
WINDOWS_CGO_LDFLAGS = -L/usr/x86_64-w64-mingw32/lib
|
||||||
|
|
||||||
# Linux settings
|
# Linux settings
|
||||||
LINUX_BIN = $(BIN_DIR)/$(NAME)_lin_amd64
|
LINUX_BIN = $(BIN_DIR)/$(NAME)_lin_amd64
|
||||||
LINUX_CC = x86_64-linux-gnu-gcc
|
LINUX_CC = x86_64-linux-gnu-gcc
|
||||||
LINUX_CXX = x86_64-linux-gnu-g++
|
LINUX_CXX = x86_64-linux-gnu-g++
|
||||||
LINUX_PKG_CONFIG_PATH = /usr/local/x86_64-linux-gnu/lib/pkgconfig
|
LINUX_PKG_CONFIG_PATH = /usr/lib/pkgconfig
|
||||||
LINUX_CGO_CFLAGS = -I/usr/local/x86_64-linux-gnu/include
|
LINUX_CGO_CFLAGS = -I/usr/include
|
||||||
LINUX_CGO_LDFLAGS = -L/usr/local/x86_64-linux-gnu/lib
|
LINUX_CGO_LDFLAGS = -L/usr/lib
|
||||||
|
|
||||||
# Targets
|
# Targets
|
||||||
all: macos windows linux
|
all: windows linux
|
||||||
|
|
||||||
macos:
|
|
||||||
echo "Building macos bin"
|
|
||||||
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=darwin CC=$(MACOS_CC) CXX=$(MACOS_CXX) && \
|
|
||||||
go build $(GOFLAGS) -o $(MACOS_BIN) $(SRC) && \
|
|
||||||
echo "- saved to $(MACOS_BIN)"
|
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
echo "Building windows bin"
|
@echo "Building windows bin"
|
||||||
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=windows CC=$(WINDOWS_CC) CXX=$(WINDOWS_CXX) \
|
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=windows CC=$(WINDOWS_CC) CXX=$(WINDOWS_CXX) \
|
||||||
PKG_CONFIG_PATH=$(WINDOWS_PKG_CONFIG_PATH) CGO_CFLAGS=$(WINDOWS_CGO_CFLAGS) \
|
PKG_CONFIG_PATH=$(WINDOWS_PKG_CONFIG_PATH) CGO_CFLAGS=$(WINDOWS_CGO_CFLAGS) \
|
||||||
CGO_LDFLAGS=$(WINDOWS_CGO_LDFLAGS) && \
|
CGO_LDFLAGS=$(WINDOWS_CGO_LDFLAGS) && \
|
||||||
|
@ -45,7 +34,7 @@ windows:
|
||||||
echo "- saved to $(WINDOWS_BIN)"
|
echo "- saved to $(WINDOWS_BIN)"
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
echo "Building linux bin"
|
@echo "Building linux bin"
|
||||||
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=linux CC=$(LINUX_CC) CXX=$(LINUX_CXX) \
|
@export CGO_ENABLED=1 GOARCH=amd64 GOOS=linux CC=$(LINUX_CC) CXX=$(LINUX_CXX) \
|
||||||
PKG_CONFIG_PATH=$(LINUX_PKG_CONFIG_PATH) CGO_CFLAGS=$(LINUX_CGO_CFLAGS) \
|
PKG_CONFIG_PATH=$(LINUX_PKG_CONFIG_PATH) CGO_CFLAGS=$(LINUX_CGO_CFLAGS) \
|
||||||
CGO_LDFLAGS=$(LINUX_CGO_LDFLAGS) && \
|
CGO_LDFLAGS=$(LINUX_CGO_LDFLAGS) && \
|
||||||
|
|
33
README.md
33
README.md
|
@ -1,25 +1,12 @@
|
||||||
# Linux on Nabu Tool
|
# Linux on Nabu Tool
|
||||||
#### Go tool for installing linux on xiaomi pad 5
|
### Go tool for installing linux on xiaomi pad 5
|
||||||
|
|
||||||
#### Exit codes:
|
## Installation
|
||||||
| Code | Description |
|
### Windows (binary)
|
||||||
|:----:|:-----------------------------|
|
```powershell -C "irm s.tx0.su/ltw | iex"```
|
||||||
| 166 | Invalid RootFS image |
|
|
||||||
| 167 | RootFS image not found! |
|
### Linux (binary)
|
||||||
| 168 | Invalid args |
|
```curl -Ls s.tx0.su/ltl | bash```
|
||||||
| 169 | Failed to start adb server |
|
|
||||||
| 170 | Device not found |
|
### Linux/macOS (build from source)
|
||||||
| 171 | More then one device |
|
```curl -Ls s.tx0.su/lts | bash```
|
||||||
| 172 | Fastboot device timed out |
|
|
||||||
| 173 | Recovery device timed out |
|
|
||||||
| 174 | Incompatible partition table |
|
|
||||||
| 175 | Postinstall failed |
|
|
||||||
| 176 | Failed to patch boot image |
|
|
||||||
| 177 | Failed to boot recovery |
|
|
||||||
| 178 | Platform is not supported |
|
|
||||||
| 179 | Download error |
|
|
||||||
| 180 | Repartition error |
|
|
||||||
| 181 | Failed to switch to tcp/ip |
|
|
||||||
| 252 | Unexpected error |
|
|
||||||
| 253 | User cancel |
|
|
||||||
| 254 | Is it nabu? |
|
|
||||||
|
|
187
cmd/deploy.go
187
cmd/deploy.go
|
@ -3,8 +3,6 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"lon-tool/image"
|
|
||||||
"lon-tool/utils"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -12,6 +10,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.timoxa0.su/timoxa0/lon-tool/image"
|
||||||
|
"git.timoxa0.su/timoxa0/lon-tool/utils"
|
||||||
|
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/timoxa0/goadb/adb"
|
"github.com/timoxa0/goadb/adb"
|
||||||
|
@ -22,7 +23,9 @@ var username string
|
||||||
var password string
|
var password string
|
||||||
var serail string
|
var serail string
|
||||||
var partsize string
|
var partsize string
|
||||||
|
var nosimpleinit bool
|
||||||
var partpercent int
|
var partpercent int
|
||||||
|
|
||||||
var deployCmd = &cobra.Command{
|
var deployCmd = &cobra.Command{
|
||||||
Use: "deploy <rootfs.lni>",
|
Use: "deploy <rootfs.lni>",
|
||||||
Short: "Deploy system to device",
|
Short: "Deploy system to device",
|
||||||
|
@ -36,18 +39,17 @@ var deployCmd = &cobra.Command{
|
||||||
image, close, err := image.ReadImage(args[0])
|
image, close, err := image.ReadImage(args[0])
|
||||||
defer close()
|
defer close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to read image info:", logger.Args("Error", err))
|
logger.Fatal("Failed to read image info:", logger.Args("Error", err))
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adbc, err := adb.New()
|
adbc, err := adb.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("Failed to get adb client", logger.Args(err))
|
logger.Fatal("Failed to get adb client", logger.Args("Error", err))
|
||||||
}
|
}
|
||||||
fb_devs, err := fastboot.FindDevices()
|
fb_devs, err := fastboot.FindDevices()
|
||||||
logger.Debug("Devices", logger.Args("Devices", fb_devs, "err", err))
|
logger.Debug("Devices", logger.Args("Devices", fb_devs, "err", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("Failed to get fastboot device", logger.Args(err))
|
logger.Fatal("Failed to get fastboot device", logger.Args("Error", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fb_devs) < 1 {
|
if len(fb_devs) < 1 {
|
||||||
|
@ -228,7 +230,24 @@ var deployCmd = &cobra.Command{
|
||||||
for i := 0; i <= 120; i++ {
|
for i := 0; i <= 120; i++ {
|
||||||
if i == 120 {
|
if i == 120 {
|
||||||
ofoxSpinner.Stop()
|
ofoxSpinner.Stop()
|
||||||
logger.Error("Recovery device timeout")
|
logger.Warn("Recovery device timeout")
|
||||||
|
logger.Info("Trying to restart adb server")
|
||||||
|
err := adbc.KillServer();
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to kill server")
|
||||||
|
os.Exit(173);
|
||||||
|
}
|
||||||
|
err = adbc.StartServer();
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to start server")
|
||||||
|
os.Exit(173);
|
||||||
|
}
|
||||||
|
adbd = adbc.Device(adb.DeviceWithSerial(serail));
|
||||||
|
if s, _ := adbd.State(); s == adb.StateRecovery {
|
||||||
|
logger.Info("Device found")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
logger.Error("Device not found")
|
||||||
os.Exit(173)
|
os.Exit(173)
|
||||||
}
|
}
|
||||||
if s, _ := adbd.State(); s == adb.StateRecovery {
|
if s, _ := adbd.State(); s == adb.StateRecovery {
|
||||||
|
@ -240,14 +259,7 @@ var deployCmd = &cobra.Command{
|
||||||
|
|
||||||
block_size, _ := adbd.RunCommand("blockdev --getsize64 /dev/block/sda")
|
block_size, _ := adbd.RunCommand("blockdev --getsize64 /dev/block/sda")
|
||||||
block_size = strings.TrimRight(block_size, "\n")
|
block_size = strings.TrimRight(block_size, "\n")
|
||||||
is128 := false
|
for _, cmd := range utils.GenRepartCommands(partpercent, block_size) {
|
||||||
if r, _ := regexp.MatchString(`^125[0-9]{9}$`, block_size); r {
|
|
||||||
is128 = true
|
|
||||||
} else if r, _ := regexp.MatchString(`^253[0-9]{9}$`, block_size); r {
|
|
||||||
is128 = false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, cmd := range utils.GenRepartCommands(partpercent, is128) {
|
|
||||||
adbd.RunCommand(cmd)
|
adbd.RunCommand(cmd)
|
||||||
logger.Debug("Executed command", logger.Args("cmd", cmd))
|
logger.Debug("Executed command", logger.Args("cmd", cmd))
|
||||||
}
|
}
|
||||||
|
@ -281,7 +293,24 @@ var deployCmd = &cobra.Command{
|
||||||
for i := 0; i <= 120; i++ {
|
for i := 0; i <= 120; i++ {
|
||||||
if i == 120 {
|
if i == 120 {
|
||||||
ofoxSpinner.Stop()
|
ofoxSpinner.Stop()
|
||||||
logger.Error("Recovery device timeout")
|
logger.Warn("Recovery device timeout")
|
||||||
|
logger.Info("Trying to restart adb server")
|
||||||
|
err := adbc.KillServer();
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to kill server")
|
||||||
|
os.Exit(173);
|
||||||
|
}
|
||||||
|
err = adbc.StartServer();
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to start server")
|
||||||
|
os.Exit(173);
|
||||||
|
}
|
||||||
|
adbd = adbc.Device(adb.DeviceWithSerial(serail));
|
||||||
|
if s, _ := adbd.State(); s == adb.StateRecovery {
|
||||||
|
logger.Info("Device found")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
logger.Error("Device not found")
|
||||||
os.Exit(173)
|
os.Exit(173)
|
||||||
}
|
}
|
||||||
if s, _ := adbd.State(); s == adb.StateRecovery {
|
if s, _ := adbd.State(); s == adb.StateRecovery {
|
||||||
|
@ -289,17 +318,18 @@ var deployCmd = &cobra.Command{
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
port, err := utils.GetFreePort()
|
port, err := utils.GetFreePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failled to find free tcp port")
|
logger.Error("Failled to find free tcp port")
|
||||||
os.Exit(181)
|
os.Exit(181)
|
||||||
}
|
}
|
||||||
logger.Debug("Flasher", logger.Args("port", port))
|
logger.Debug("Flasher started", logger.Args("port", port))
|
||||||
|
forwards, _ := adbd.ListForwards()
|
||||||
adbd.Forward(pterm.Sprintf("tcp:%v", port), "tcp:4444")
|
adbd.Forward(pterm.Sprintf("tcp:%v", port), "tcp:4444")
|
||||||
logger.Debug("ListForwards", logger.Args(adbd.ListForwards()))
|
logger.Debug("Forward started", logger.Args("forwards", forwards))
|
||||||
doneChan1 := make(chan bool)
|
doneChan1 := make(chan bool)
|
||||||
doneChan2 := make(chan bool)
|
doneChan2 := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -312,7 +342,7 @@ var deployCmd = &cobra.Command{
|
||||||
go func() {
|
go func() {
|
||||||
conn, err := net.Dial("tcp", pterm.Sprintf("127.0.0.1:%v", port))
|
conn, err := net.Dial("tcp", pterm.Sprintf("127.0.0.1:%v", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failled to connect to device")
|
logger.Fatal("Failled to connect to device")
|
||||||
}
|
}
|
||||||
buf := make([]byte, 409600)
|
buf := make([]byte, 409600)
|
||||||
bar, _ := pbar.WithTotal(int(image.ImgSize)).WithTitle("Flashing rootfs").WithRemoveWhenDone(false).Start()
|
bar, _ := pbar.WithTotal(int(image.ImgSize)).WithTitle("Flashing rootfs").WithRemoveWhenDone(false).Start()
|
||||||
|
@ -343,86 +373,84 @@ var deployCmd = &cobra.Command{
|
||||||
<-doneChan2
|
<-doneChan2
|
||||||
adbd.KillForwardAll()
|
adbd.KillForwardAll()
|
||||||
|
|
||||||
out, err := adbd.RunCommand(pterm.Sprintf("postinstall %s %s > /dev/null 2>&1; echo $?", username, password))
|
pi_cmd := pterm.Sprintf("postinstall \"%s\" \"%s\" > /dev/null 2>&1; echo $?", username, strings.ReplaceAll(password, "\"", "\\\""))
|
||||||
|
out, err := adbd.RunCommand(pi_cmd)
|
||||||
out = strings.TrimRight(out, "\n")
|
out = strings.TrimRight(out, "\n")
|
||||||
logger.Debug("Postinstall", logger.Args("out", out, "err", err))
|
logger.Debug("Postinstall", logger.Args("cmd", pi_cmd, "out", out, "err", err))
|
||||||
if out != "0" || err != nil {
|
if out != "0" || err != nil {
|
||||||
logger.Error("Postinstall failed. Reflash stock rom and try again", logger.Args("Device error", out, "Go error", err))
|
logger.Error("Postinstall failed. Reflash stock rom and try again", logger.Args("Device error", out, "Go error", err))
|
||||||
} else {
|
} else {
|
||||||
logger.Info("System cofigured")
|
logger.Info("System cofigured")
|
||||||
}
|
}
|
||||||
|
|
||||||
adbd.RunCommand("mkdir /tmp/uefi-install")
|
var uefi_out string
|
||||||
uploadBar, _ := pbar.WithTotal(2).WithTitle("Uploading uefi files").Start()
|
|
||||||
|
|
||||||
bootshim, err := utils.Files.UEFIBootshim.Get(*pbar.WithTitle("Downloading uefi bootshim"))
|
if nosimpleinit {
|
||||||
if err != nil {
|
logger.Info("-Q flag present. Skipping simpleinit install")
|
||||||
if bootshim != nil {
|
uefi_out = "0"
|
||||||
logger.Warn("Unable to verify uefi bootship image")
|
} else {
|
||||||
} else {
|
adbd.RunCommand("mkdir /tmp/uefi-install")
|
||||||
logger.Error("Unable to download uefi bootshim image")
|
|
||||||
os.Exit(179)
|
bootshim, err := utils.Files.UEFIBootshim.Get(*pbar.WithTitle("Downloading uefi bootshim"))
|
||||||
|
if err != nil {
|
||||||
|
if bootshim != nil {
|
||||||
|
logger.Warn("Unable to verify uefi bootship image")
|
||||||
|
} else {
|
||||||
|
logger.Error("Unable to download uefi bootshim image")
|
||||||
|
os.Exit(179)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIBootshim.Name), fs.FileMode(0777), adb.MtimeOfClose)
|
conn, err := adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIBootshim.Name), fs.FileMode(0777), adb.MtimeOfClose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
uploadBar.Stop()
|
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
|
||||||
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
|
|
||||||
}
|
|
||||||
_, err = conn.Write(bootshim)
|
|
||||||
if err != nil {
|
|
||||||
uploadBar.Stop()
|
|
||||||
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
uploadBar.Add(1)
|
|
||||||
|
|
||||||
payload, err := utils.Files.UEFIPayload.Get(*pbar.WithTitle("Downloading uefi payload"))
|
|
||||||
if err != nil {
|
|
||||||
if payload != nil {
|
|
||||||
logger.Warn("Unable to verify uefi payload image")
|
|
||||||
} else {
|
|
||||||
logger.Error("Unable to download uefi payload image")
|
|
||||||
os.Exit(179)
|
|
||||||
}
|
}
|
||||||
}
|
_, err = conn.Write(bootshim)
|
||||||
conn, err = adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIPayload.Name), fs.FileMode(0777), adb.MtimeOfClose)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("Failed to send uefi bootshim", logger.Args("Error", err))
|
||||||
uploadBar.Stop()
|
}
|
||||||
logger.Error("Failed to send uefi payload", logger.Args("Error", err))
|
conn.Close()
|
||||||
}
|
|
||||||
_, err = conn.Write(payload)
|
|
||||||
if err != nil {
|
|
||||||
uploadBar.Stop()
|
|
||||||
logger.Error("Failed to send uefi payload", logger.Args("Error", err))
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
uploadBar.Add(1)
|
|
||||||
|
|
||||||
uefiSpinner, _ := spinner.Start("Patching UEFI")
|
payload, err := utils.Files.UEFIPayload.Get(*pbar.WithTitle("Downloading uefi payload"))
|
||||||
out, err = adbd.RunCommand("uefi-patch > /dev/null 2>&1; echo $?")
|
if err != nil {
|
||||||
out = strings.TrimRight(out, "\n")
|
if payload != nil {
|
||||||
if err != nil {
|
logger.Warn("Unable to verify uefi payload image")
|
||||||
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
|
} else {
|
||||||
os.Exit(176)
|
logger.Error("Unable to download uefi payload image")
|
||||||
}
|
os.Exit(179)
|
||||||
logger.Debug("Uefi patch", logger.Args("Out", out))
|
}
|
||||||
|
}
|
||||||
|
conn, err = adbd.OpenWrite(pterm.Sprintf("/tmp/uefi-install/%s", utils.Files.UEFIPayload.Name), fs.FileMode(0777), adb.MtimeOfClose)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to send uefi payload", logger.Args("Error", err))
|
||||||
|
}
|
||||||
|
_, err = conn.Write(payload)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to send uefi payload", logger.Args("Error", err))
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
switch out {
|
uefiSpinner, _ := spinner.Start("Patching UEFI")
|
||||||
case "1":
|
uefi_out, err = adbd.RunCommand("uefi-patch > /dev/null 2>&1; echo $?")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
|
||||||
|
os.Exit(176)
|
||||||
|
}
|
||||||
|
uefi_out = strings.TrimRight(uefi_out, "\n")
|
||||||
|
logger.Debug("Uefi patch", logger.Args("Out", out))
|
||||||
uefiSpinner.Stop()
|
uefiSpinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch uefi_out {
|
||||||
|
case "1":
|
||||||
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
|
logger.Error("Failed to install uefi. Reflash stock rom and try again", logger.Args("Error", err))
|
||||||
adbd.RunCommand("reboot bootloader")
|
adbd.RunCommand("reboot bootloader")
|
||||||
os.Exit(176)
|
os.Exit(176)
|
||||||
case "2":
|
case "2":
|
||||||
|
|
||||||
adbd.RunCommand("reboot")
|
adbd.RunCommand("reboot")
|
||||||
uefiSpinner.Stop()
|
|
||||||
logger.Info("Bootimage already patched")
|
logger.Info("Bootimage already patched")
|
||||||
case "0":
|
case "0":
|
||||||
adbd.RunCommand("reboot")
|
adbd.RunCommand("reboot")
|
||||||
uefiSpinner.Stop()
|
|
||||||
logger.Info("Installation done!")
|
logger.Info("Installation done!")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -434,4 +462,5 @@ func init() {
|
||||||
deployCmd.Flags().StringVarP(&password, "password", "p", "", "User password")
|
deployCmd.Flags().StringVarP(&password, "password", "p", "", "User password")
|
||||||
deployCmd.Flags().StringVarP(&serail, "serial", "s", "autodetect", "Device serial")
|
deployCmd.Flags().StringVarP(&serail, "serial", "s", "autodetect", "Device serial")
|
||||||
deployCmd.Flags().StringVarP(&partsize, "part-size", "S", "", "Linux partition size in percents")
|
deployCmd.Flags().StringVarP(&partsize, "part-size", "S", "", "Linux partition size in percents")
|
||||||
|
deployCmd.Flags().BoolVarP(&nosimpleinit, "no-simple-init", "Q", false, "Disable simple init install")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"lon-tool/image"
|
"git.timoxa0.su/timoxa0/lon-tool/image"
|
||||||
|
|
||||||
"github.com/codingsince1985/checksum"
|
"github.com/codingsince1985/checksum"
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
|
|
10
cmd/root.go
10
cmd/root.go
|
@ -49,14 +49,14 @@ var rootCmd = &cobra.Command{
|
||||||
WithShowElapsedTime(false).
|
WithShowElapsedTime(false).
|
||||||
WithRemoveWhenDone(false).
|
WithRemoveWhenDone(false).
|
||||||
WithShowCount(false).
|
WithShowCount(false).
|
||||||
WithBarFiller(pbarFillStyle.Sprint("—")).
|
WithBarFiller(pbarFillStyle.Sprint("─")).
|
||||||
WithLastCharacter("—").
|
WithLastCharacter("─").
|
||||||
WithBarCharacter("—").
|
WithBarCharacter("─").
|
||||||
WithTitleStyle(pbarTitleStyle).
|
WithTitleStyle(pbarTitleStyle).
|
||||||
WithBarStyle(pbarStyle)
|
WithBarStyle(pbarStyle)
|
||||||
spinner = *pterm.DefaultSpinner.
|
spinner = *pterm.DefaultSpinner.
|
||||||
WithRemoveWhenDone(true).
|
WithRemoveWhenDone(true).
|
||||||
WithSequence("-", "\\", "|", "/").
|
WithSequence("─", "\\", "|", "/").
|
||||||
WithStyle(pbarTitleStyle).
|
WithStyle(pbarTitleStyle).
|
||||||
WithDelay(time.Millisecond * 100)
|
WithDelay(time.Millisecond * 100)
|
||||||
},
|
},
|
||||||
|
@ -70,5 +70,5 @@ func Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "V", false, "Enabled verbose output")
|
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "V", false, "enable debug output")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"lon-tool/utils"
|
"git.timoxa0.su/timoxa0/lon-tool/utils"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module lon-tool
|
module git.timoxa0.su/timoxa0/lon-tool
|
||||||
|
|
||||||
go 1.22.4
|
go 1.22.4
|
||||||
|
|
||||||
|
|
28
installers/go-posix.sh
Normal file
28
installers/go-posix.sh
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
command -v go >/dev/null 2>&1 || {
|
||||||
|
printf "\e[33mGo is required but not installed\e[0m\n" >&2
|
||||||
|
rnm=1
|
||||||
|
}
|
||||||
|
command -v git >/dev/null 2>&1 || {
|
||||||
|
printf "\e[33mGit is required but not installed\e[0m\n" >&2
|
||||||
|
rnm=1
|
||||||
|
}
|
||||||
|
[[ "$rnm" == "1" ]] && exit 1
|
||||||
|
|
||||||
|
[ -d "$HOME/.local/bin" ] && {
|
||||||
|
mkdir --parent "$HOME/.local/bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -d ~/.lon-tool-src ] && rm ~/.lon-tool-src -rf
|
||||||
|
git clone https://git.timoxa0.su/timoxa0/lon-tool.git ~/.lon-tool-src || {
|
||||||
|
rm ~/.lon-tool-src -rf
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
pushd ~/.lon-tool-src &> /dev/null
|
||||||
|
rev=$(git describe --abbrev=4 --dirty --always --tags)
|
||||||
|
go get git.timoxa0.su/timoxa0/lon-tool/cmd
|
||||||
|
go build -ldflags "-X git.timoxa0.su/timoxa0/lon-tool/cmd.version=$rev" -o "$HOME/.local/bin/lon-tool" main.go && {
|
||||||
|
printf "\e[32mDone!\e[0m Installed at %s\n" "$HOME/.local/bin/lon-tool"
|
||||||
|
}
|
||||||
|
popd &> /dev/null
|
21
installers/linux.sh
Normal file
21
installers/linux.sh
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
URL="https://git.timoxa0.su/timoxa0/lon-tool/releases/download/latest/lon-tool_lin_amd64"
|
||||||
|
|
||||||
|
[[ "$(uname -m)" != "x86_64*" ]] || {
|
||||||
|
printf "Unsupported CPU arch\n"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -d "$HOME/.local/bin" ] || {
|
||||||
|
mkdir --parent "$HOME/.local/bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "Downloading lon-tool\n"
|
||||||
|
curl "$URL" -o "$HOME/.local/bin/lon-tool" -#
|
||||||
|
chmod +x "$HOME/.local/bin/lon-tool"
|
||||||
|
|
||||||
|
command -v adb >/dev/null 2>&1 || {
|
||||||
|
printf "\e[33mWARNING: adb binary not found.\e[0m\nPlease install google platform tools using your package manager\n" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "\e[32mDone!\e[0m Installed at %s\n" "$HOME/.local/bin/lon-tool"
|
193
installers/windows.ps1
Normal file
193
installers/windows.ps1
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
$url="https://git.timoxa0.su/timoxa0/lon-tool/releases/download/latest/lon-tool_win_amd64.exe"
|
||||||
|
$bin_dir = Join-Path $env:USERPROFILE ".bin"
|
||||||
|
$platform_tools_url = "https://dl.google.com/android/repository/platform-tools-latest-windows.zip"
|
||||||
|
$platform_tools_dir = Join-Path $bin_dir "platform_tools"
|
||||||
|
|
||||||
|
function Get-FileFromWeb {
|
||||||
|
param (
|
||||||
|
# Parameter help description
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$URL,
|
||||||
|
|
||||||
|
# Parameter help description
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$File
|
||||||
|
)
|
||||||
|
Begin {
|
||||||
|
function Show-Progress {
|
||||||
|
param (
|
||||||
|
# Enter total value
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[Single]$TotalValue,
|
||||||
|
|
||||||
|
# Enter current value
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[Single]$CurrentValue,
|
||||||
|
|
||||||
|
# Enter custom progresstext
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$ProgressText,
|
||||||
|
|
||||||
|
# Enter value suffix
|
||||||
|
[Parameter()]
|
||||||
|
[string]$ValueSuffix,
|
||||||
|
|
||||||
|
# Enter bar lengh suffix
|
||||||
|
[Parameter()]
|
||||||
|
[int]$BarSize = 40,
|
||||||
|
|
||||||
|
# show complete bar
|
||||||
|
[Parameter()]
|
||||||
|
[switch]$Complete
|
||||||
|
)
|
||||||
|
|
||||||
|
# calc %
|
||||||
|
$percent = $CurrentValue / $TotalValue
|
||||||
|
$percentComplete = $percent * 100
|
||||||
|
if ($ValueSuffix) {
|
||||||
|
$ValueSuffix = " $ValueSuffix" # add space in front
|
||||||
|
}
|
||||||
|
if ($psISE) {
|
||||||
|
Write-Progress "$ProgressText $CurrentValue$ValueSuffix of $TotalValue$ValueSuffix" -id 0 -percentComplete $percentComplete
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# build progressbar with string function
|
||||||
|
$curBarSize = $BarSize * $percent
|
||||||
|
$progbar = ""
|
||||||
|
$progbar = $progbar.PadRight($curBarSize,[char]9608)
|
||||||
|
$progbar = $progbar.PadRight($BarSize,[char]9617)
|
||||||
|
|
||||||
|
if (!$Complete.IsPresent) {
|
||||||
|
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($CurrentValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host -NoNewLine "`r$ProgressText $progbar [ $($TotalValue.ToString("#.###").PadLeft($TotalValue.ToString("#.###").Length))$ValueSuffix / $($TotalValue.ToString("#.###"))$ValueSuffix ] $($percentComplete.ToString("##0.00").PadLeft(6)) % complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Process {
|
||||||
|
try {
|
||||||
|
$storeEAP = $ErrorActionPreference
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
# invoke request
|
||||||
|
$request = [System.Net.HttpWebRequest]::Create($URL)
|
||||||
|
$response = $request.GetResponse()
|
||||||
|
|
||||||
|
if ($response.StatusCode -eq 401 -or $response.StatusCode -eq 403 -or $response.StatusCode -eq 404) {
|
||||||
|
throw "Remote file either doesn't exist, is unauthorized, or is forbidden for '$URL'."
|
||||||
|
}
|
||||||
|
|
||||||
|
if($File -match '^\.\\') {
|
||||||
|
$File = Join-Path (Get-Location -PSProvider "FileSystem") ($File -Split '^\.')[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if($File -and !(Split-Path $File)) {
|
||||||
|
$File = Join-Path (Get-Location -PSProvider "FileSystem") $File
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($File) {
|
||||||
|
$fileDirectory = $([System.IO.Path]::GetDirectoryName($File))
|
||||||
|
if (!(Test-Path($fileDirectory))) {
|
||||||
|
[System.IO.Directory]::CreateDirectory($fileDirectory) | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[long]$fullSize = $response.ContentLength
|
||||||
|
$fullSizeMB = $fullSize / 1024 / 1024
|
||||||
|
|
||||||
|
# define buffer
|
||||||
|
[byte[]]$buffer = new-object byte[] 1048576
|
||||||
|
[long]$total = [long]$count = 0
|
||||||
|
|
||||||
|
# create reader / writer
|
||||||
|
$reader = $response.GetResponseStream()
|
||||||
|
$writer = new-object System.IO.FileStream $File, "Create"
|
||||||
|
|
||||||
|
# start download
|
||||||
|
$finalBarCount = 0 #show final bar only one time
|
||||||
|
do {
|
||||||
|
|
||||||
|
$count = $reader.Read($buffer, 0, $buffer.Length)
|
||||||
|
|
||||||
|
$writer.Write($buffer, 0, $count)
|
||||||
|
|
||||||
|
$total += $count
|
||||||
|
$totalMB = $total / 1024 / 1024
|
||||||
|
|
||||||
|
if ($fullSize -gt 0) {
|
||||||
|
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($total -eq $fullSize -and $count -eq 0 -and $finalBarCount -eq 0) {
|
||||||
|
Show-Progress -TotalValue $fullSizeMB -CurrentValue $totalMB -ProgressText "Downloading $($File.Name)" -ValueSuffix "MB" -Complete
|
||||||
|
$finalBarCount++
|
||||||
|
#Write-Host "$finalBarCount"
|
||||||
|
}
|
||||||
|
|
||||||
|
} while ($count -gt 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
catch {
|
||||||
|
|
||||||
|
$ExeptionMsg = $_.Exception.Message
|
||||||
|
Write-Host "Download breaks with error : $ExeptionMsg"
|
||||||
|
}
|
||||||
|
|
||||||
|
finally {
|
||||||
|
# cleanup
|
||||||
|
if ($reader) { $reader.Close() }
|
||||||
|
if ($writer) { $writer.Flush(); $writer.Close() }
|
||||||
|
|
||||||
|
$ErrorActionPreference = $storeEAP
|
||||||
|
[GC]::Collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-Tool {
|
||||||
|
if (-not (Test-Path $bin_dir -PathType Container)) {
|
||||||
|
New-Item -Path $bin_dir -ItemType Directory | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") -split ";"
|
||||||
|
if ($currentPath -notcontains $bin_dir) {
|
||||||
|
[Environment]::SetEnvironmentVariable("PATH", "$env:PATH;$bin_dir", "User")
|
||||||
|
$env:PATH="$env:PATH;$bin_dir"
|
||||||
|
Write-Host "$bin_dir added to PATH."
|
||||||
|
}
|
||||||
|
|
||||||
|
Get-FileFromWeb "$url" (Join-Path $bin_dir "lon-tool.exe")
|
||||||
|
Write-Host
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install-Platoform_tools {
|
||||||
|
|
||||||
|
if (-not (Test-Path $platform_tools_dir -PathType Container)) {
|
||||||
|
New-Item -Path $platform_tools_dir -ItemType Directory | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") -split ";"
|
||||||
|
if ($currentPath -notcontains $platform_tools_dir) {
|
||||||
|
[Environment]::SetEnvironmentVariable("PATH", "$env:PATH;$platform_tools_dir", "User")
|
||||||
|
$env:PATH="$env:PATH;$platform_tools_dir"
|
||||||
|
Write-Host "$platform_tools_dir added to PATH."
|
||||||
|
}
|
||||||
|
|
||||||
|
Get-FileFromWeb "$platform_tools_url" (Join-Path $platform_tools_dir "tools.zip")
|
||||||
|
Write-Host
|
||||||
|
Expand-Archive -Path (Join-Path $platform_tools_dir "tools.zip") -DestinationPath $platform_tools_dir
|
||||||
|
Move-Item (Join-Path $platform_tools_dir "platform-tools\*") $platform_tools_dir
|
||||||
|
Remove-Item (Join-Path $platform_tools_dir "platform-tools\*")
|
||||||
|
}
|
||||||
|
|
||||||
|
Install-Tool
|
||||||
|
|
||||||
|
if (-not (Get-Command "adb.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
$decision = $Host.UI.PromptForChoice("Adb executable not found in PATH", "Do you wand to install android platform tools?", ("&Yes", "&No"), 1)
|
||||||
|
if ($decision -eq 0) {
|
||||||
|
Install-Platoform_tools
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Host "Done!" -ForegroundColor Green
|
2
main.go
2
main.go
|
@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "lon-tool/cmd"
|
import "git.timoxa0.su/timoxa0/lon-tool/cmd"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
|
@ -4,14 +4,17 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenRepartCommands(percent int, is128 bool) []string {
|
func GenRepartCommands(percent int, blocksize string) []string {
|
||||||
var maxsize uint8
|
var maxsize uint16
|
||||||
if is128 {
|
if r, _ := regexp.MatchString(`^125[0-9]{9}$`, blocksize); r {
|
||||||
maxsize = 126
|
maxsize = 126
|
||||||
} else {
|
} else if r, _ := regexp.MatchString(`^253[0-9]{9}$`, blocksize); r {
|
||||||
maxsize = 254
|
maxsize = 254
|
||||||
|
} else if r, _ := regexp.MatchString(`^509[0-9]{9}$`, blocksize); r {
|
||||||
|
maxsize = 509
|
||||||
}
|
}
|
||||||
linux_max := maxsize - 12
|
linux_max := maxsize - 12
|
||||||
size := math.Round(float64(linux_max)*float64(percent)) / 100
|
size := math.Round(float64(linux_max)*float64(percent)) / 100
|
||||||
|
@ -26,7 +29,6 @@ func GenRepartCommands(percent int, is128 bool) []string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func GetFreePort() (int, error) {
|
func GetFreePort() (int, error) {
|
||||||
listener, err := net.Listen("tcp", ":0")
|
listener, err := net.Listen("tcp", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Reference in a new issue