Skip to content

Commit

Permalink
v0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
SydneyOwl committed Nov 29, 2024
1 parent 3533f29 commit b6e7cce
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 200 deletions.
8 changes: 5 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ This software is based on several open-source tools, allowing users to:
## Usage

+ `./g90toolkit -i` Enter interactive mode. Follow the instructions to provide the relevant information. The software will automatically decrypt the firmware, replace images and text, re-encrypt the firmware, and flash it into the device.

![](./assets/7as51-w9pu6.gif)
+ `./g90toolkit fullexec --firmware <encrypted_firmware> --key <your_key>
--device <optional_serial_port> --logo-path <optional_logo_path>
--text <optional_boot_text> --output <optional_output_path>`
Automatically decrypt firmware, apply changes, re-encrypt firmware,
save to file, and flash into device.

+ `./g90toolkit decrypt --firmware <encrypted_firmware> --output <path_to_save_decrypted_firmware> --key <your_key>` Decrypt firmware using specified key.

Expand Down
Binary file removed assets/7as51-w9pu6.gif
Binary file not shown.
14 changes: 9 additions & 5 deletions cmd/decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"github.com/sydneyowl/g90toolkit/tools"
)

var output string

// decryptCmd represents the decrypt command
var decryptCmd = &cobra.Command{
Use: "decrypt",
Expand All @@ -18,11 +16,11 @@ var decryptCmd = &cobra.Command{
fmt.Println("Please provide a key!")
return
}
if output == "" {
if Output == "" {
fmt.Println("Please provide a output path!")
return
}
if err := tools.DoDecryptAndSave(Key, FirmwarePath, output); err != nil {
if err := tools.DoDecryptAndSave(Key, FirmwarePath, Output); err != nil {
fmt.Printf("Error: %v", err)
} else {
fmt.Printf("Firmware decrypted using specified key successfully.")
Expand All @@ -41,5 +39,11 @@ func init() {

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
decryptCmd.Flags().StringVar(&output, "output", "", "Specify a path to save decrypted firmware.")
decryptCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a firmware to decrypt.")
decryptCmd.Flags().StringVar(&Key, "key", "", "Specify a key to decrypt/encrypt firmware.")
decryptCmd.Flags().StringVar(&Output, "output", "", "Specify a path to save decrypted firmware.")

decryptCmd.MarkFlagRequired("firmware")
decryptCmd.MarkFlagRequired("key")
decryptCmd.MarkFlagRequired("output")
}
12 changes: 9 additions & 3 deletions cmd/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ var encryptCmd = &cobra.Command{
fmt.Println("Please provide a key!")
return
}
if output == "" {
if Output == "" {
fmt.Println("Please provide a output path!")
return
}
if err := tools.DoEncryptAndSave(Key, FirmwarePath, output); err != nil {
if err := tools.DoEncryptAndSave(Key, FirmwarePath, Output); err != nil {
fmt.Printf("Error: %v", err)
} else {
fmt.Printf("Firmware encrypted using specified key successfully.")
Expand All @@ -41,5 +41,11 @@ func init() {
// is called directly, e.g.:
// encryptCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

encryptCmd.Flags().StringVar(&output, "output", "", "Specify a path to save encrypted firmware.")
encryptCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a firmware to encrypt.")
encryptCmd.Flags().StringVar(&Key, "key", "", "Specify a key to decrypt/encrypt firmware.")
encryptCmd.Flags().StringVar(&Output, "output", "", "Specify a path to save decrypted firmware.")

encryptCmd.MarkFlagRequired("firmware")
encryptCmd.MarkFlagRequired("key")
encryptCmd.MarkFlagRequired("output")
}
20 changes: 16 additions & 4 deletions cmd/flashfw.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"github.com/sydneyowl/g90toolkit/lib/g90updatefw"
"github.com/sydneyowl/g90toolkit/tools"
"os"
"os/user"
"runtime"
"strings"
"time"
)

var deviceFile string

// flashfwCmd represents the flashfw command
var flashfwCmd = &cobra.Command{
Use: "flashfw",
Expand All @@ -32,7 +32,14 @@ machines it will be similar to COMM2.
You should start the program with the programming cable plugged in
and the power disconnected from the radio.`,
Run: func(cmd *cobra.Command, args []string) {
serial, err := g90updatefw.SerialOpen(deviceFile, 115200)
if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
currentUser, _ := user.Current()
if currentUser.Uid != "0" && !NoRootCheck {
fmt.Println("WARNING: THIS PROGRAM IS NOT RUNNING WITH SUDO. SUDO IS NEEDED WHEN FLASHING FIRMWARE.")
fmt.Println("SUPPRESS THIS WARNING WITH --no-root-check.")
}
}
serial, err := g90updatefw.SerialOpen(DeviceFile, 115200)
if err != nil {
fmt.Printf("Error opening device: %v", err)
return
Expand Down Expand Up @@ -98,5 +105,10 @@ func init() {

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
flashfwCmd.Flags().StringVar(&deviceFile, "device", "", "name of the serial port connected to the Xiegu radio.")
flashfwCmd.Flags().StringVar(&DeviceFile, "device", "", "name of the serial port connected to the Xiegu radio.")
flashfwCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a firmware to flash.")
flashfwCmd.Flags().BoolVar(&NoRootCheck, "no-root-check", false, "Don't check if the program is running with sudo")

flashfwCmd.MarkFlagRequired("device")
flashfwCmd.MarkFlagRequired("firmware")
}
162 changes: 162 additions & 0 deletions cmd/fullexec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package cmd

import (
"fmt"
"github.com/Kei-K23/spinix"
"github.com/spf13/cobra"
"github.com/sydneyowl/g90toolkit/lib/g90updatefw"
"github.com/sydneyowl/g90toolkit/tools"
"os"
"os/user"
"regexp"
"runtime"
"time"
)

// fullexecCmd represents the fullexec command
var fullexecCmd = &cobra.Command{
Use: "fullexec",
Short: "Exec all procedure for you",
Long: `Auto decrypt firmware,patch logo and text, re-encrypt firmware, and flash it into device.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("-> FULLEXEC MODE")
if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
currentUser, _ := user.Current()
if currentUser.Uid != "0" && !NoRootCheck {
fmt.Println("WARNING: THIS PROGRAM IS NOT RUNNING WITH SUDO. SUDO IS NEEDED WHEN FLASHING FIRMWARE.")
fmt.Println("SUPPRESS THIS WARNING WITH --no-root-check.")
}
}
fwdata, err := os.ReadFile(FirmwarePath)
if err != nil {
fmt.Printf("Failed to read %s: %v", FirmwarePath, err)
return
}
if tools.CheckDecrypted(fwdata) {
fmt.Println("WARNING: THIS IS A DECRYPTED FIRMWARE. IT IS RECOMMENDED TO USE ORIGINAL ONE.")
}
decryptedData, err := tools.DoDecrypt(Key, fwdata)
if err != nil {
fmt.Printf("Failed to decrypt %s: %v", FirmwarePath, err)
return
}
fmt.Println("Firmware decrypted.")
if LogoPath == "" {
fmt.Println("Boot logo is not provided. Skipping...")
} else {
logoData, err := os.ReadFile(LogoPath)
if err != nil {
fmt.Printf("failed to read logo: %v\n", err)
return
}
fmt.Println("Trying to patch logo...")
if err := tools.PatchBootLogo(logoData, decryptedData); err != nil {
fmt.Printf("failed to patch boot logo: %v\n", err)
return
}
fmt.Println("Done.")
}

if Text == "" {
fmt.Println("Boot text is not provided. Skipping...")
} else {
re := regexp.MustCompile("^[a-zA-Z0-9]+$")
if !re.MatchString(Text) {
fmt.Println("Only numbers or letters are allowed.")
return
}
if len(Text) > 6 {
fmt.Println("Only six-digit numbers or letters are allowed.")
return
}
tmp := []byte(Text)
textData := make([]byte, 8)
copy(textData, tmp)
if err := tools.PatchBootText(textData, decryptedData); err != nil {
fmt.Printf("failed to patch boot text: %v\n", err)
return
}
fmt.Println("Boot text patched successfully.")
}
fmt.Println("All steps done. Encrypting firmware...")
encryptedData, err := tools.DoEncrypt(Key, decryptedData)
if err != nil {
fmt.Printf("Failed to encrypt %s: %v", FirmwarePath, err)
return
}
if Output == "" {
fmt.Println("Output path is not set. Skipping...")
} else {
if err := os.WriteFile(Output, encryptedData, 0777); err != nil {
fmt.Printf("failed to save firmware: %v", err)
return
}
fmt.Println("Firmware saved successfully.")
}
if DeviceFile == "" {
fmt.Println("Device is not set. Skipping...")
} else {
fmt.Println("Plug in the cable, then press enter...")
fmt.Scanln()
fmt.Println(`
To flash your device, please:
> 1. Disconnect power cable from the radio.
> 2. Reconnect power cable to the radio.
> 3. Press the volume button and while holding it in,
> 4. Press the power button until the radio begins erasing the existing firmware.
`)
// start update radio, 0: writing 1:done
progChan := make(chan uint, 4)
serial, err := g90updatefw.SerialOpen(DeviceFile, 115200)
if err != nil {
fmt.Printf("Error opening device: %v", err)
return
}
defer serial.Close()
go g90updatefw.UpdateRadio(serial, encryptedData, progChan)
<-progChan
fmt.Print("Waiting for device ready...")
<-progChan
fmt.Print("\rWaiting for device ready...Done\n")
fmt.Print("Erasing and waiting for fw...")
<-progChan
fmt.Print("\rErasing and waiting for fw...Done\n")
spinner := spinix.NewSpinner().
SetSpinnerColor("\033[34m").
SetMessage("Uploading firmware...").
SetMessageColor("\033[36m").
SetSpeed(100 * time.Millisecond).
SetLastFrame("✔").
SetLastFrameColor("\033[34m").
SetLastMessage("Uploading firmware...Done").
SetLastMessageColor("\033[36m")
spinner.Start()
<-progChan
spinner.Stop()
}
},
}

func init() {
rootCmd.AddCommand(fullexecCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// fullexecCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// fullexecCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
fullexecCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a firmware to modify.")
fullexecCmd.Flags().StringVar(&Key, "key", "", "Specify a key to decrypt/encrypt firmware.")
fullexecCmd.Flags().StringVar(&DeviceFile, "device", "", "name of the serial port connected to the Xiegu radio. (OPTIONAL)")
fullexecCmd.Flags().StringVar(&LogoPath, "logo-path", "", "Specify the logo path you want to apply to the firmware. (OPTIONAL)")
fullexecCmd.Flags().StringVar(&Text, "text", "", "Specify the text you want to apply to the firmware. (OPTIONAL)")
fullexecCmd.Flags().BoolVar(&NoRootCheck, "no-root-check", false, "Don't check if the program is running with sudo")
fullexecCmd.Flags().StringVar(&Output, "output", "", "Specify a path to save patched firmware. (OPTIONAl)")

fullexecCmd.MarkFlagRequired("firmware")
fullexecCmd.MarkFlagRequired("key")
}
4 changes: 4 additions & 0 deletions cmd/getinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ var firmwareInfoCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(firmwareInfoCmd)
firmwareInfoCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a firmware to read.")
firmwareInfoCmd.Flags().StringVar(&Key, "key", "", "Specify a key to decrypt/encrypt firmware.(optional)")

firmwareInfoCmd.MarkFlagRequired("firmware")
}
19 changes: 11 additions & 8 deletions cmd/patchimg.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"os"
)

var logoPath string

// patchimgCmd represents the patchimg command
var patchimgCmd = &cobra.Command{
Use: "patchimg",
Expand All @@ -20,15 +18,15 @@ var patchimgCmd = &cobra.Command{
fmt.Printf("failed to read firmware: %v", err)
return
}
if output == "" {
if Output == "" {
fmt.Println("Please provide a output path!")
return
}
if logoPath == "" {
if LogoPath == "" {
fmt.Println("Please specify a logo path using --logo-path!")
return
}
logoData, err := os.ReadFile(logoPath)
logoData, err := os.ReadFile(LogoPath)
if err != nil {
fmt.Printf("failed to read logo: %v\n", err)
return
Expand All @@ -42,7 +40,7 @@ var patchimgCmd = &cobra.Command{
fmt.Printf("failed to patch boot logo: %v\n", err)
return
}
err = os.WriteFile(output, data, 0777)
err = os.WriteFile(Output, data, 0777)
if err != nil {
fmt.Printf("failed to patch image: %v\n", err)
return
Expand All @@ -62,6 +60,11 @@ func init() {

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
patchimgCmd.Flags().StringVar(&logoPath, "logo-path", "", "Specify the logo path you want to apply to the firmware.")
patchimgCmd.Flags().StringVar(&output, "output", "", "Specify a path to save patched firmware.")
patchimgCmd.Flags().StringVar(&FirmwarePath, "firmware", "", "Specify a decrypted firmware to path.")
patchimgCmd.Flags().StringVar(&LogoPath, "logo-path", "", "Specify the logo path you want to apply to the firmware.")
patchimgCmd.Flags().StringVar(&Output, "output", "", "Specify a path to save patched firmware.")

patchimgCmd.MarkFlagRequired("firmware")
patchimgCmd.MarkFlagRequired("logo-path")
patchimgCmd.MarkFlagRequired("output")
}
Loading

0 comments on commit b6e7cce

Please sign in to comment.