mirror of
https://github.com/blacktop/ipsw.git
synced 2026-05-08 12:22:26 +00:00
chore: more cleanup and refactoring
This commit is contained in:
@@ -104,7 +104,7 @@ var deviceTreeCmd = &cobra.Command{
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse device-tree")
|
||||
}
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Model: %s", s.Model))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Model: %s", s.ProductType))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Board Config: %s", s.BoardConfig))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Product Name: %s", s.ProductName))
|
||||
}
|
||||
@@ -143,7 +143,7 @@ var deviceTreeCmd = &cobra.Command{
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse device-tree")
|
||||
}
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Model: %s", s.Model))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Model: %s", s.ProductType))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Board Config: %s", s.BoardConfig))
|
||||
utils.Indent(log.Info, 2)(fmt.Sprintf("Product Name: %s", s.ProductName))
|
||||
}
|
||||
|
||||
@@ -122,7 +122,6 @@ var otaDLCmd = &cobra.Command{
|
||||
otaInfo := viper.GetBool("download.ota.info")
|
||||
otaInfoType := viper.GetString("download.ota.info-type")
|
||||
output := viper.GetString("download.ota.output")
|
||||
|
||||
// verify args
|
||||
if len(dyldArches) > 0 && !remoteDyld {
|
||||
return errors.New("--dyld-arch || -a can only be used with --dyld || -d")
|
||||
@@ -361,8 +360,7 @@ var otaDLCmd = &cobra.Command{
|
||||
// download file
|
||||
downloader.URL = url
|
||||
downloader.DestName = destName
|
||||
err = downloader.Do()
|
||||
if err != nil {
|
||||
if err := downloader.Do(); err != nil {
|
||||
return fmt.Errorf("failed to download file: %v", err)
|
||||
}
|
||||
} else {
|
||||
|
||||
+11
-10
@@ -26,13 +26,13 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/blacktop/ipsw/internal/download"
|
||||
"github.com/blacktop/ipsw/pkg/info"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ var infoCmd = &cobra.Command{
|
||||
SilenceErrors: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
var pIPSW *info.Info
|
||||
var i *info.Info
|
||||
|
||||
if Verbose {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
@@ -76,7 +76,7 @@ var infoCmd = &cobra.Command{
|
||||
Insecure: insecure,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create new remote zip reader")
|
||||
return fmt.Errorf("failed to create new remote zip reader: %w", err)
|
||||
}
|
||||
if listFiles {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
|
||||
@@ -87,9 +87,9 @@ var infoCmd = &cobra.Command{
|
||||
}
|
||||
w.Flush()
|
||||
} else {
|
||||
pIPSW, err = info.ParseZipFiles(zr.File)
|
||||
i, err = info.ParseZipFiles(zr.File)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to extract remote plists")
|
||||
return fmt.Errorf("failed to parse plists in zip: %w", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -113,17 +113,18 @@ var infoCmd = &cobra.Command{
|
||||
w.Flush()
|
||||
} else {
|
||||
var err error
|
||||
pIPSW, err = info.Parse(fPath)
|
||||
i, err = info.Parse(fPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to extract and parse IPSW info")
|
||||
return fmt.Errorf("failed to parse plists: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !listFiles {
|
||||
fmt.Println("\n[IPSW Info]")
|
||||
fmt.Println("===========")
|
||||
fmt.Println(pIPSW)
|
||||
title := fmt.Sprintf("[%s Info]", i.Plists.Type)
|
||||
fmt.Printf("\n%s\n", title)
|
||||
fmt.Println(strings.Repeat("=", len(title)))
|
||||
fmt.Println(i)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+40
-36
@@ -25,12 +25,16 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/blacktop/ipsw/internal/download"
|
||||
"github.com/blacktop/ipsw/pkg/info"
|
||||
"github.com/blacktop/ipsw/pkg/ota/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -95,7 +99,7 @@ var updateDBCmd = &cobra.Command{
|
||||
|
||||
zr, err := download.NewRemoteZipReader(url, &download.RemoteConfig{})
|
||||
if err != nil {
|
||||
// log.WithError(err).Fatal("failed to create remote zip reader")
|
||||
log.Error("failed to create remote zip reader")
|
||||
continue
|
||||
}
|
||||
i, err := info.ParseZipFiles(zr.File)
|
||||
@@ -115,42 +119,41 @@ var updateDBCmd = &cobra.Command{
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to parse remote zip")
|
||||
}
|
||||
if err := i.GetDevices(&devices); err != nil {
|
||||
log.WithError(err).Fatal("failed to get devices")
|
||||
if i.Plists.Type == "OTA" {
|
||||
foundMap := false
|
||||
for _, f := range zr.File {
|
||||
if regexp.MustCompile(`.*plist$`).MatchString(f.Name) {
|
||||
switch {
|
||||
case strings.HasSuffix(f.Name, "AssetData/boot/Firmware/device_map.plist"):
|
||||
foundMap = true
|
||||
dat := make([]byte, f.UncompressedSize64)
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to open file within zip")
|
||||
}
|
||||
defer rc.Close()
|
||||
io.ReadFull(rc, dat)
|
||||
dmap, err := types.ParseDeviceMap(dat)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to parse device map")
|
||||
}
|
||||
if err := i.GetDevicesFromMap(dmap, &devices); err != nil {
|
||||
log.WithError(err).Fatal("failed to get devices")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundMap {
|
||||
if err := i.GetDevices(&devices); err != nil {
|
||||
log.WithError(err).Fatal("failed to get devices")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := i.GetDevices(&devices); err != nil {
|
||||
log.WithError(err).Fatal("failed to get devices")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// for _, version := range []string{"9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0"} {
|
||||
// for _, version := range []string{"10.0", "11.0", "12.0", "13.0", "14.0", "15.0"} {
|
||||
// ipsws, err := download.GetAllIPSW(version)
|
||||
// if err != nil {
|
||||
// log.WithError(err).Fatal("failed to get IPSWs")
|
||||
// }
|
||||
// unique := make(map[string]bool, len(ipsws))
|
||||
// uniqueIPSWs := make([]download.IPSW, len(unique))
|
||||
// for _, i := range ipsws {
|
||||
// if len(i.URL) != 0 {
|
||||
// if !unique[i.URL] {
|
||||
// uniqueIPSWs = append(uniqueIPSWs, i)
|
||||
// unique[i.URL] = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for _, ipsw := range uniqueIPSWs {
|
||||
// zr, err := download.NewRemoteZipReader(ipsw.URL, &download.RemoteConfig{})
|
||||
// if err != nil {
|
||||
// log.WithError(err).Fatal("failed to create remote zip reader")
|
||||
// }
|
||||
// i, err := info.ParseZipFiles(zr.File)
|
||||
// if err != nil {
|
||||
// // log.WithError(err).Fatal("failed to parse remote ipsw")
|
||||
// continue
|
||||
// }
|
||||
// if err := i.GetDevices(&devices); err != nil {
|
||||
// log.WithError(err).Fatal("failed to get devices")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
} else { // TODO: add default "latest" URL streams here to collect new devices
|
||||
itunes, err := download.NewMacOsXML()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("failed to create itunes API")
|
||||
@@ -170,6 +173,7 @@ var updateDBCmd = &cobra.Command{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OUTPUT JSON
|
||||
dat, err := json.Marshal(devices)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -16,7 +17,6 @@ import (
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/blacktop/ipsw/internal/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Img4 DeviceTree object
|
||||
@@ -47,9 +47,11 @@ type DeviceTree map[string]Properties
|
||||
|
||||
// Summary object
|
||||
type Summary struct {
|
||||
ProductName string
|
||||
BoardConfig string
|
||||
Model string
|
||||
ProductName string
|
||||
ProductDescription string
|
||||
ProductType string
|
||||
BoardConfig string
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Summary prints out a summary of the DeviceTree
|
||||
@@ -67,11 +69,14 @@ func (dtree *DeviceTree) Summary() (*Summary, error) {
|
||||
if product, ok := (c)["product"]["product-name"].(string); ok {
|
||||
summary.ProductName = product
|
||||
}
|
||||
if productDesc, ok := (c)["product"]["product-description"].(string); ok {
|
||||
summary.ProductDescription = productDesc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if model, ok := (*dtree)["device-tree"]["model"].(string); ok {
|
||||
summary.Model = model
|
||||
summary.ProductType = model
|
||||
compatible := (*dtree)["device-tree"]["compatible"]
|
||||
switch reflect.TypeOf(compatible).Kind() {
|
||||
case reflect.Slice:
|
||||
@@ -87,6 +92,24 @@ func (dtree *DeviceTree) Summary() (*Summary, error) {
|
||||
return nil, fmt.Errorf("devicetree model is not a string")
|
||||
}
|
||||
|
||||
if stamp, ok := (*dtree)["device-tree"]["time-stamp"].(string); ok {
|
||||
location, err := time.LoadLocation("PST8PDT")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load location PST8PDT: %v", err)
|
||||
}
|
||||
layout := "Mon Jan 2 15:04:05 MST 2006"
|
||||
t, err := time.ParseInLocation(layout, stamp, location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zone, _ := time.Now().Zone()
|
||||
location, err = time.LoadLocation(zone)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load location %s: %v", zone, err)
|
||||
}
|
||||
summary.Timestamp = t.In(location)
|
||||
}
|
||||
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
@@ -135,17 +158,6 @@ func (dtree *DeviceTree) GetModel() (string, error) {
|
||||
return "", fmt.Errorf("failed to get model")
|
||||
}
|
||||
|
||||
func findDeviceTreesInList(list []string) []string {
|
||||
var validDT = regexp.MustCompile(`.*DeviceTree.*im4p$`)
|
||||
dTrees := []string{}
|
||||
for _, v := range list {
|
||||
if validDT.MatchString(v) {
|
||||
dTrees = append(dTrees, v)
|
||||
}
|
||||
}
|
||||
return dTrees
|
||||
}
|
||||
|
||||
func parseValue(value []byte) interface{} {
|
||||
// remove trailing NULLs
|
||||
value = bytes.TrimRight(value[:], "\x00")
|
||||
@@ -280,7 +292,7 @@ func Parse(ipswPath string) (map[string]*DeviceTree, error) {
|
||||
|
||||
zr, err := zip.OpenReader(ipswPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to open ipsw as zip")
|
||||
return nil, fmt.Errorf("failed to open zip: %s", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
@@ -293,7 +305,7 @@ func Parse(ipswPath string) (map[string]*DeviceTree, error) {
|
||||
|
||||
dt[filepath.Base(f.Name)], err = ParseImg4Data(dtData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse DeviceTree")
|
||||
return nil, fmt.Errorf("failed to parse Img4 DeviceTree: %v", err)
|
||||
}
|
||||
} else if regexp.MustCompile(`.*DeviceTree.*img3$`).MatchString(f.Name) {
|
||||
dtData := make([]byte, f.UncompressedSize64)
|
||||
@@ -303,7 +315,7 @@ func Parse(ipswPath string) (map[string]*DeviceTree, error) {
|
||||
|
||||
dt[filepath.Base(f.Name)], err = ParseImg3Data(dtData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse DeviceTree")
|
||||
return nil, fmt.Errorf("failed to parse Img3 DeviceTree: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,7 +339,7 @@ func ParseZipFiles(files []*zip.File) (map[string]*DeviceTree, error) {
|
||||
|
||||
dt[filepath.Base(f.Name)], err = ParseImg4Data(dtData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse DeviceTree")
|
||||
return nil, fmt.Errorf("failed to parse Img4 DeviceTree: %v", err)
|
||||
}
|
||||
} else if regexp.MustCompile(`.*DeviceTree.*img3$`).MatchString(f.Name) {
|
||||
dtData := make([]byte, f.UncompressedSize64)
|
||||
@@ -337,7 +349,7 @@ func ParseZipFiles(files []*zip.File) (map[string]*DeviceTree, error) {
|
||||
|
||||
dt[filepath.Base(f.Name)], err = ParseImg3Data(dtData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse DeviceTree: %w", err)
|
||||
return nil, fmt.Errorf("failed to parse Img3 DeviceTree: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,19 +360,14 @@ func ParseZipFiles(files []*zip.File) (map[string]*DeviceTree, error) {
|
||||
// Extract extracts DeviceTree(s) from ipsw
|
||||
func Extract(ipsw, destPath string) error {
|
||||
_, err := utils.Unzip(ipsw, destPath, func(f *zip.File) bool {
|
||||
var validDT = regexp.MustCompile(`.*DeviceTree.*im4p$`)
|
||||
if validDT.MatchString(f.Name) {
|
||||
if regexp.MustCompile(`.*DeviceTree.*im4p$`).MatchString(f.Name) {
|
||||
return true
|
||||
}
|
||||
validDT = regexp.MustCompile(`.*DeviceTree.*img3$`)
|
||||
if validDT.MatchString(f.Name) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return regexp.MustCompile(`.*DeviceTree.*img3$`).MatchString(f.Name)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to extract DeviceTree from ipsw")
|
||||
return fmt.Errorf("failed to extract DeviceTree: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+153
-101
@@ -1,147 +1,199 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/blacktop/ipsw/internal/utils"
|
||||
"github.com/apex/log"
|
||||
"github.com/blacktop/ipsw/pkg/ota/types"
|
||||
"github.com/blacktop/ipsw/pkg/xcode"
|
||||
)
|
||||
|
||||
type Board struct {
|
||||
CPU string `json:"cpu,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
CpuID int `json:"cpu_id,omitempty"`
|
||||
Arch string `json:"arch,omitempty"`
|
||||
CpuISA string `json:"cpu_isa,omitempty"`
|
||||
BoardConfig string `json:"board_config,omitempty"`
|
||||
BoardID int `json:"board_id,omitempty"`
|
||||
CPU string `json:"cpu,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
PlatformName string `json:"platform_name,omitempty"`
|
||||
ChipID string `json:"cpuid,omitempty"`
|
||||
Arch string `json:"arch,omitempty"`
|
||||
CpuISA string `json:"cpuisa,omitempty"`
|
||||
BoardID string `json:"board_id,omitempty"`
|
||||
BasebandChipID string `json:"bbid,omitempty"`
|
||||
KernelCacheType string `json:"kc_type,omitempty"`
|
||||
ResearchSupported bool `json:"research_support,omitempty"`
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Boards []Board `json:"boards,omitempty"`
|
||||
MemClass int `json:"mem_class,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"desc,omitempty"`
|
||||
Boards map[string]Board `json:"boards,omitempty"`
|
||||
MemClass string `json:"mem_class,omitempty"`
|
||||
SDKPlatform string `json:"sdk,omitempty"`
|
||||
}
|
||||
|
||||
type Devices map[string]Device
|
||||
|
||||
func (i *Info) GetDevices(devs *Devices) error {
|
||||
var xdev xcode.Device
|
||||
if i.DeviceTrees != nil && len(i.DeviceTrees) > 0 {
|
||||
for _, dtree := range i.DeviceTrees {
|
||||
dt, _ := dtree.Summary()
|
||||
prodName := dt.ProductName
|
||||
dt, err := dtree.Summary()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting device tree summary: %v", err)
|
||||
}
|
||||
|
||||
if devices, err := xcode.GetDevices(); err == nil {
|
||||
for _, device := range devices {
|
||||
if device.ProductType == dt.Model {
|
||||
xdev = device
|
||||
if len(prodName) == 0 {
|
||||
prodName = xdev.ProductDescription
|
||||
var kctype string
|
||||
if kcs := i.Plists.BuildManifest.GetKernelForModel(strings.ToLower(dt.BoardConfig)); kcs != nil {
|
||||
if len(kcs) == 1 {
|
||||
kctype = kcs[0][strings.LastIndex(kcs[0], ".")+1:]
|
||||
} else {
|
||||
kctype = kcs[0][strings.LastIndex(kcs[0], ".")+1:] // FIXME: what?
|
||||
}
|
||||
}
|
||||
|
||||
xdev, err := xcode.GetDeviceForProd(dt.ProductType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting device %s in xcode device list: %v", dt.ProductType, err)
|
||||
}
|
||||
|
||||
if len(dt.ProductType) > 0 {
|
||||
if _, ok := (*devs)[dt.ProductType]; !ok {
|
||||
if dt.ProductName != dt.ProductDescription {
|
||||
(*devs)[dt.ProductType] = Device{
|
||||
Name: dt.ProductName,
|
||||
Description: dt.ProductDescription,
|
||||
Boards: make(map[string]Board),
|
||||
MemClass: strconv.Itoa(xdev.DeviceTrait.DevicePerformanceMemoryClass),
|
||||
}
|
||||
} else {
|
||||
(*devs)[dt.ProductType] = Device{
|
||||
Name: dt.ProductName,
|
||||
Boards: make(map[string]Board),
|
||||
MemClass: strconv.Itoa(xdev.DeviceTrait.DevicePerformanceMemoryClass),
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if i.Plists.Restore != nil { // IPSW
|
||||
var boards []Board
|
||||
for _, board := range i.Plists.Restore.DeviceMap {
|
||||
if board.BoardConfig == strings.ToLower(dt.BoardConfig) {
|
||||
proc := getProcessor(board.Platform)
|
||||
boards = append(boards, Board{
|
||||
CPU: proc.Name,
|
||||
Platform: board.Platform,
|
||||
CpuID: board.CPID,
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: xdev.DeviceTrait.PreferredArchitecture,
|
||||
BoardConfig: dt.BoardConfig,
|
||||
BoardID: board.BDID,
|
||||
})
|
||||
}
|
||||
}
|
||||
if _, ok := (*devs)[dt.Model]; !ok {
|
||||
(*devs)[dt.Model] = Device{
|
||||
Name: prodName,
|
||||
Boards: boards,
|
||||
MemClass: xdev.DeviceTrait.DevicePerformanceMemoryClass,
|
||||
}
|
||||
}
|
||||
} else { // OTA
|
||||
for _, board := range i.Plists.BuildIdentities {
|
||||
if board.Info.DeviceClass == strings.ToLower(dt.BoardConfig) {
|
||||
if _, ok := (*devs)[dt.Model]; !ok {
|
||||
chipID, err := utils.ConvertStrToInt(board.ApChipID)
|
||||
if err != nil {
|
||||
chipID = 0
|
||||
}
|
||||
boardID, err := utils.ConvertStrToInt(board.ApBoardID)
|
||||
if err != nil {
|
||||
boardID = 0
|
||||
}
|
||||
proc := getProcessor(xdev.Platform)
|
||||
(*devs)[dt.Model] = Device{
|
||||
Name: prodName,
|
||||
Boards: []Board{
|
||||
{
|
||||
CPU: proc.Name,
|
||||
Platform: xdev.Platform,
|
||||
CpuID: int(chipID),
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: xdev.DeviceTrait.PreferredArchitecture,
|
||||
BoardConfig: dt.BoardConfig,
|
||||
BoardID: int(boardID),
|
||||
},
|
||||
},
|
||||
MemClass: xdev.DeviceTrait.DevicePerformanceMemoryClass,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
proc := getProcessor(xdev.Platform)
|
||||
if len(proc.Name) == 0 {
|
||||
log.Errorf("no processor for %s for board %s: %s", dt.ProductType, dt.BoardConfig, dt.ProductName)
|
||||
}
|
||||
|
||||
(*devs)[dt.ProductType].Boards[dt.BoardConfig] = Board{
|
||||
CPU: proc.Name,
|
||||
Platform: xdev.Platform,
|
||||
// PlatformName: d.PlatformName,
|
||||
ChipID: i.Plists.BuildManifest.BuildIdentities[0].ApChipID,
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: xdev.DeviceTrait.PreferredArchitecture,
|
||||
BoardID: i.Plists.BuildManifest.BuildIdentities[0].ApBoardID,
|
||||
BasebandChipID: i.Plists.BuildManifest.BuildIdentities[0].BbChipID,
|
||||
KernelCacheType: kctype,
|
||||
// ResearchSupported: d.ResearchSupported,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if i.Plists.Restore != nil {
|
||||
var prodType string
|
||||
var prodName string
|
||||
for idx, prod := range i.Plists.Restore.SupportedProductTypes {
|
||||
if devices, err := xcode.GetDevices(); err == nil {
|
||||
for _, device := range devices {
|
||||
if device.ProductType == prod {
|
||||
xdev = device
|
||||
if len(prodName) == 0 {
|
||||
prodName = xdev.ProductDescription
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if len(prodName) == 0 {
|
||||
var arch string
|
||||
var memClass string
|
||||
if len(i.Plists.Restore.SupportedProductTypes) == 1 {
|
||||
prodType = i.Plists.Restore.SupportedProductTypes[0]
|
||||
} else {
|
||||
prodType = i.Plists.Restore.SupportedProductTypes[0]
|
||||
log.Error("BAD ASSUMPTIONS: multiple product types in restore plist")
|
||||
}
|
||||
kcs := i.Plists.BuildManifest.GetKernelCaches()
|
||||
for _, dev := range i.Plists.Restore.DeviceMap {
|
||||
if xdev, err := xcode.GetDeviceForProd(prodType); err == nil {
|
||||
prodName = xdev.ProductDescription
|
||||
arch = xdev.DeviceTrait.PreferredArchitecture
|
||||
memClass = strconv.Itoa(xdev.DeviceTrait.DevicePerformanceMemoryClass)
|
||||
}
|
||||
if len(prodName) == 0 {
|
||||
if i.Plists.OTAInfo != nil {
|
||||
prodName = "FIXME - " + i.Plists.OTAInfo.MobileAssetProperties.DeviceName
|
||||
} else {
|
||||
prodName = "FIXME"
|
||||
}
|
||||
}
|
||||
if _, ok := (*devs)[prod]; !ok {
|
||||
proc := getProcessor(i.Plists.Restore.DeviceMap[idx].Platform)
|
||||
(*devs)[prod] = Device{
|
||||
if _, ok := (*devs)[prodType]; !ok {
|
||||
proc := getProcessor(dev.Platform)
|
||||
if len(proc.Name) == 0 {
|
||||
log.Errorf("no processor for %s for board %s: %s", dev.Platform, dev.BoardConfig, prodName)
|
||||
}
|
||||
(*devs)[prodType] = Device{
|
||||
Name: prodName,
|
||||
Boards: []Board{
|
||||
{
|
||||
CPU: proc.Name,
|
||||
Platform: i.Plists.Restore.DeviceMap[idx].Platform,
|
||||
CpuID: i.Plists.Restore.DeviceMap[idx].CPID,
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: xdev.DeviceTrait.PreferredArchitecture,
|
||||
BoardConfig: strings.ToUpper(i.Plists.Restore.DeviceMap[idx].BoardConfig),
|
||||
BoardID: i.Plists.Restore.DeviceMap[idx].BDID,
|
||||
Boards: map[string]Board{
|
||||
strings.ToUpper(dev.BoardConfig): {
|
||||
CPU: proc.Name,
|
||||
Platform: dev.Platform,
|
||||
// PlatformName: d.PlatformName,
|
||||
ChipID: i.Plists.BuildManifest.BuildIdentities[0].ApChipID,
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: arch,
|
||||
BoardID: i.Plists.BuildManifest.BuildIdentities[0].ApBoardID,
|
||||
BasebandChipID: i.Plists.BuildManifest.BuildIdentities[0].BbChipID,
|
||||
KernelCacheType: kcs[dev.BoardConfig][0][strings.LastIndex(kcs[dev.BoardConfig][0], ".")+1:],
|
||||
// ResearchSupported: d.ResearchSupported,
|
||||
},
|
||||
},
|
||||
MemClass: xdev.DeviceTrait.DevicePerformanceMemoryClass,
|
||||
MemClass: memClass,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic("unsupport IPSW/OTA type w/ no devicetree?")
|
||||
panic("unsupported IPSW/OTA type")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mLBTypeToBoardConfig(bc string, mlbType string) string {
|
||||
return mlbType + strings.ToUpper(strings.TrimPrefix(bc, strings.ToLower(mlbType)))
|
||||
}
|
||||
|
||||
func (i *Info) GetDevicesFromMap(dmap *types.DeviceMap, devs *Devices) error {
|
||||
for bc, d := range *dmap {
|
||||
if len(d.ProductType) > 0 {
|
||||
if _, ok := (*devs)[d.ProductType]; !ok {
|
||||
if d.ProductName != d.ProductDescription {
|
||||
(*devs)[d.ProductType] = Device{
|
||||
Name: d.ProductName,
|
||||
Description: d.ProductDescription,
|
||||
Boards: make(map[string]Board),
|
||||
MemClass: d.DevicePerformanceMemoryClass,
|
||||
SDKPlatform: d.SDKPlatform,
|
||||
}
|
||||
} else {
|
||||
(*devs)[d.ProductType] = Device{
|
||||
Name: d.ProductName,
|
||||
Boards: make(map[string]Board),
|
||||
MemClass: d.DevicePerformanceMemoryClass,
|
||||
SDKPlatform: d.SDKPlatform,
|
||||
}
|
||||
}
|
||||
}
|
||||
proc := getProcessor(d.Platform)
|
||||
if len(proc.Name) == 0 {
|
||||
log.Errorf("no processor for %s for board %s: %s", d.Platform, bc, d.ProductName)
|
||||
}
|
||||
(*devs)[d.ProductType].Boards[mLBTypeToBoardConfig(bc, d.MLBType)] = Board{
|
||||
CPU: proc.Name,
|
||||
Platform: d.Platform,
|
||||
PlatformName: d.PlatformName,
|
||||
ChipID: d.ChipID,
|
||||
CpuISA: proc.CPUISA,
|
||||
Arch: d.KernelMachOArchitecture,
|
||||
BoardID: d.BoardID,
|
||||
BasebandChipID: d.BasebandChipID,
|
||||
KernelCacheType: d.KernelCacheType,
|
||||
ResearchSupported: d.ResearchSupported,
|
||||
}
|
||||
} else {
|
||||
log.Debugf("Board %s has no product type", bc)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-9
@@ -144,17 +144,17 @@ func (i *Info) String() string {
|
||||
devices, err := xcode.GetDevices()
|
||||
if err == nil {
|
||||
for _, device := range devices {
|
||||
if device.ProductType == dt.Model {
|
||||
if device.ProductType == dt.ProductType {
|
||||
prodName = device.ProductDescription
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prodName = dt.Model
|
||||
prodName = dt.ProductType
|
||||
}
|
||||
}
|
||||
iStr += fmt.Sprintf("\n%s\n", prodName)
|
||||
iStr += fmt.Sprintf(" > %s_%s_%s\n", dt.Model, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion)
|
||||
iStr += fmt.Sprintf(" > %s_%s_%s\n", dt.ProductType, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion)
|
||||
if len(kcs[strings.ToLower(dt.BoardConfig)]) > 0 {
|
||||
iStr += fmt.Sprintf(" - KernelCache: %s\n", kcs[strings.ToLower(dt.BoardConfig)])
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func (i *Info) String() string {
|
||||
if len(bls[strings.ToLower(dt.BoardConfig)]) > 0 {
|
||||
iStr += fmt.Sprintf(" - BootLoaders\n")
|
||||
for _, bl := range bls[strings.ToLower(dt.BoardConfig)] {
|
||||
if _, key, err := getApFirmwareKey(dt.Model, i.Plists.BuildManifest.ProductBuildVersion, filepath.Base(bl)); err != nil {
|
||||
if _, key, err := getApFirmwareKey(dt.ProductType, i.Plists.BuildManifest.ProductBuildVersion, filepath.Base(bl)); err != nil {
|
||||
iStr += fmt.Sprintf(" * %s\n", filepath.Base(bl))
|
||||
} else {
|
||||
iStr += fmt.Sprintf(" * %s 🔑 -> %s\n", filepath.Base(bl), key)
|
||||
@@ -191,7 +191,7 @@ func (i *Info) GetFolder() string {
|
||||
var devs []string
|
||||
for _, dtree := range i.DeviceTrees {
|
||||
dt, _ := dtree.Summary()
|
||||
devs = append(devs, dt.Model)
|
||||
devs = append(devs, dt.ProductType)
|
||||
}
|
||||
devs = utils.SortDevices(utils.Unique(devs))
|
||||
return fmt.Sprintf("%s__%s", i.Plists.BuildManifest.ProductBuildVersion, getAbbreviatedDevList(devs))
|
||||
@@ -202,7 +202,7 @@ func (i *Info) GetFolders() []string {
|
||||
var folders []string
|
||||
for _, dtree := range i.DeviceTrees {
|
||||
dt, _ := dtree.Summary()
|
||||
folders = append(folders, fmt.Sprintf("%s_%s_%s", dt.Model, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion))
|
||||
folders = append(folders, fmt.Sprintf("%s_%s_%s", dt.ProductType, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion))
|
||||
}
|
||||
return folders
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func (i *Info) GetFolderForFile(fileName string) string {
|
||||
dt, _ := dtree.Summary()
|
||||
for _, file := range files[strings.ToLower(dt.BoardConfig)] {
|
||||
if strings.Contains(fileName, filepath.Base(file)) {
|
||||
return fmt.Sprintf("%s_%s_%s", dt.Model, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion)
|
||||
return fmt.Sprintf("%s_%s_%s", dt.ProductType, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ func (i *Info) getFolders() []folder {
|
||||
for _, dtree := range i.DeviceTrees {
|
||||
dt, _ := dtree.Summary()
|
||||
fs = append(fs, folder{
|
||||
Name: fmt.Sprintf("%s_%s_%s", dt.Model, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion),
|
||||
Name: fmt.Sprintf("%s_%s_%s", dt.ProductType, strings.ToUpper(dt.BoardConfig), i.Plists.BuildManifest.ProductBuildVersion),
|
||||
KernelCaches: kcs[strings.ToLower(dt.BoardConfig)],
|
||||
})
|
||||
}
|
||||
@@ -285,7 +285,7 @@ func (i *Info) GetDevicesForKernelCache(kc string) []string {
|
||||
for _, dtree := range i.DeviceTrees {
|
||||
dt, _ := dtree.Summary()
|
||||
if strings.ToLower(bconf) == strings.ToLower(dt.BoardConfig) {
|
||||
devices = append(devices, dt.Model)
|
||||
devices = append(devices, dt.ProductType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,6 +341,7 @@ func Parse(ipswPath string) (*Info, error) {
|
||||
// ParseZipFiles parses plist files and devicetree in a remote zip file
|
||||
func ParseZipFiles(files []*zip.File) (*Info, error) {
|
||||
var err error
|
||||
|
||||
i := &Info{}
|
||||
|
||||
i.Plists, err = plist.ParseZipFiles(files)
|
||||
|
||||
@@ -17,6 +17,20 @@ type BuildManifest struct {
|
||||
SupportedProductTypes []string `plist:"SupportedProductTypes,omitempty"`
|
||||
}
|
||||
|
||||
func (b *BuildManifest) String() string {
|
||||
var out string
|
||||
out += "BuildManifest:\n"
|
||||
out += fmt.Sprintf(" ManifestVersion: %d\n", b.ManifestVersion)
|
||||
out += fmt.Sprintf(" ProductBuildVersion: %s\n", b.ProductBuildVersion)
|
||||
out += fmt.Sprintf(" ProductVersion: %s\n", b.ProductVersion)
|
||||
out += fmt.Sprintf(" SupportedProductTypes: %v\n", b.SupportedProductTypes)
|
||||
out += " BuildIdentities:\n"
|
||||
for _, bID := range b.BuildIdentities {
|
||||
out += fmt.Sprintf(" -\n%s", bID.String())
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type buildIdentity struct {
|
||||
ApBoardID string
|
||||
ApChipID string
|
||||
@@ -42,6 +56,23 @@ type buildIdentity struct {
|
||||
EUICCChipID int `plist:"eUICC,ChipID,omitempty"`
|
||||
}
|
||||
|
||||
func (i buildIdentity) String() string {
|
||||
var out string
|
||||
out += fmt.Sprintf(" ProductMarketingVersion: %s\n", i.ProductMarketingVersion)
|
||||
out += fmt.Sprintf(" ApBoardID: %s\n", i.ApBoardID)
|
||||
out += fmt.Sprintf(" ApChipID: %s\n", i.ApChipID)
|
||||
out += fmt.Sprintf(" ApSecurityDomain: %s\n", i.ApSecurityDomain)
|
||||
out += fmt.Sprintf(" BbChipID: %s\n", i.BbChipID)
|
||||
out += fmt.Sprintf(" Info:\n%s", i.Info.String())
|
||||
out += fmt.Sprintf(" Manifest:\n")
|
||||
for k, v := range i.Manifest {
|
||||
if len(v.Info.Path) > 0 {
|
||||
out += fmt.Sprintf(" %s: %s\n", k, v.String())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type buildIdentityInfo struct {
|
||||
BuildNumber string
|
||||
CodeName string `plist:"BuildTrain,omitempty"`
|
||||
@@ -56,6 +87,27 @@ type buildIdentityInfo struct {
|
||||
VariantContents map[string]string
|
||||
}
|
||||
|
||||
func (i buildIdentityInfo) String() string {
|
||||
return fmt.Sprintf(
|
||||
" BuildNumber: %s\n"+
|
||||
" CodeName: %s\n"+
|
||||
" DeviceClass: %s\n"+
|
||||
" FDRSupport: %t\n"+
|
||||
" MinimumSystemPartition: %d\n"+
|
||||
" MobileDeviceMinVersion: %s\n"+
|
||||
" RestoreBehavior: %s\n"+
|
||||
" Variant: %s\n",
|
||||
i.BuildNumber,
|
||||
i.CodeName,
|
||||
i.DeviceClass,
|
||||
i.FDRSupport,
|
||||
i.MinimumSystemPartition,
|
||||
i.MobileDeviceMinVersion,
|
||||
i.RestoreBehavior,
|
||||
i.Variant,
|
||||
)
|
||||
}
|
||||
|
||||
type buildIdentityManifest struct {
|
||||
Digest []byte
|
||||
BuildString string `plist:"BuildString,omitempty"`
|
||||
@@ -63,6 +115,14 @@ type buildIdentityManifest struct {
|
||||
Trusted bool
|
||||
}
|
||||
|
||||
func (m buildIdentityManifest) String() string {
|
||||
var bs string
|
||||
if len(m.BuildString) > 0 {
|
||||
bs = fmt.Sprintf(" (%s)", m.BuildString)
|
||||
}
|
||||
return fmt.Sprintf("%s%s", m.Info.Path, bs)
|
||||
}
|
||||
|
||||
type buildIdentityManifestInfo struct {
|
||||
IsFTAB bool
|
||||
IsFUDFirmware bool `plist:"IsFUDFirmware,omitempty"`
|
||||
@@ -95,6 +155,18 @@ func (b *BuildManifest) GetKernelCaches() map[string][]string {
|
||||
return kernelCaches
|
||||
}
|
||||
|
||||
func (b *BuildManifest) GetKernelForModel(model string) []string {
|
||||
kcs := b.GetKernelCaches()
|
||||
if v, ok := kcs[model]; ok {
|
||||
return v
|
||||
} else if len(kcs) == 1 {
|
||||
for _, v := range kcs {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildManifest) GetBootLoaders() map[string][]string {
|
||||
bootLoaders := make(map[string][]string, len(b.BuildIdentities))
|
||||
for _, bID := range b.BuildIdentities {
|
||||
@@ -118,6 +190,11 @@ func (b *BuildManifest) GetBootLoaders() map[string][]string {
|
||||
bootLoaders[bID.Info.DeviceClass] = append(bootLoaders[bID.Info.DeviceClass], bID.Manifest["LLB"].Info.Path)
|
||||
}
|
||||
}
|
||||
if !utils.StrSliceHas(bootLoaders[bID.Info.DeviceClass], bID.Manifest["SEP"].Info.Path) {
|
||||
if len(bID.Manifest["SEP"].Info.Path) > 0 {
|
||||
bootLoaders[bID.Info.DeviceClass] = append(bootLoaders[bID.Info.DeviceClass], bID.Manifest["SEP"].Info.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return bootLoaders
|
||||
}
|
||||
|
||||
+6
-4
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
// Plists IPSW/OTA plists object
|
||||
type Plists struct {
|
||||
Type string
|
||||
*BuildManifest
|
||||
*Restore
|
||||
*AssetDataInfo
|
||||
@@ -116,7 +117,7 @@ func Parse(path string) (*Plists, error) {
|
||||
|
||||
// ParseZipFiles parses plists in remote ipsw zip
|
||||
func ParseZipFiles(files []*zip.File) (*Plists, error) {
|
||||
ipsw := &Plists{}
|
||||
ipsw := &Plists{Type: "IPSW"}
|
||||
|
||||
for _, f := range files {
|
||||
if regexp.MustCompile(`.*plist$`).MatchString(f.Name) {
|
||||
@@ -143,6 +144,7 @@ func ParseZipFiles(files []*zip.File) (*Plists, error) {
|
||||
return nil, err
|
||||
}
|
||||
case strings.HasSuffix(f.Name, "AssetData/Info.plist"):
|
||||
ipsw.Type = "OTA"
|
||||
dat, err := readZipFile(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read plist file: %s", err)
|
||||
@@ -152,6 +154,7 @@ func ParseZipFiles(files []*zip.File) (*Plists, error) {
|
||||
return nil, err
|
||||
}
|
||||
case strings.EqualFold(f.Name, "Info.plist"):
|
||||
ipsw.Type = "OTA"
|
||||
dat, err := readZipFile(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read plist file: %s", err)
|
||||
@@ -168,11 +171,10 @@ func ParseZipFiles(files []*zip.File) (*Plists, error) {
|
||||
}
|
||||
|
||||
func (p *Plists) GetOSType() string {
|
||||
if len(p.BuildManifest.BuildIdentities[0].Info.VariantContents["OS"]) > 0 {
|
||||
return p.BuildManifest.BuildIdentities[0].Info.VariantContents["OS"]
|
||||
}
|
||||
if p.OTAInfo != nil {
|
||||
return p.OTAInfo.MobileAssetProperties.ReleaseType
|
||||
} else if len(p.BuildManifest.BuildIdentities[0].Info.VariantContents["OS"]) > 0 {
|
||||
return p.BuildManifest.BuildIdentities[0].Info.VariantContents["OS"]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -84,3 +84,39 @@ func GetDevices() ([]Device, error) {
|
||||
|
||||
return devices, nil
|
||||
}
|
||||
|
||||
// GetDeviceForProd returns the device matching a given product type
|
||||
func GetDeviceForProd(prod string) (*Device, error) {
|
||||
var devices []Device
|
||||
|
||||
err := json.Unmarshal(traitsData, &devices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
if device.ProductType == prod {
|
||||
return &device, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("device not found")
|
||||
}
|
||||
|
||||
// GetDeviceForModel returns the device matching a given model
|
||||
func GetDeviceForModel(model string) (*Device, error) {
|
||||
var devices []Device
|
||||
|
||||
err := json.Unmarshal(traitsData, &devices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
if device.Target == model {
|
||||
return &device, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("device not found")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user