mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-12 09:54:36 +01:00
Clover.app v1.14
Bootloader installation is now performed by CloverDaemonNew (one command line in less).
This commit is contained in:
parent
37338e285b
commit
aa207eaa44
@ -7,7 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
95337172237070CD003F1AF4 /* Cloverhelper in Copy tools */ = {isa = PBXBuildFile; fileRef = 9533716F237070B3003F1AF4 /* Cloverhelper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
9533718323709517003F1AF4 /* bootsectors-install in Resources */ = {isa = PBXBuildFile; fileRef = 9533718223709517003F1AF4 /* bootsectors-install */; };
|
||||
9533718523709A36003F1AF4 /* bootsectors-install in Copy CloverV2 */ = {isa = PBXBuildFile; fileRef = 9533718223709517003F1AF4 /* bootsectors-install */; };
|
||||
953BC20323720C0A0039755D /* FixedWidthViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 953BC20223720C0A0039755D /* FixedWidthViews.swift */; };
|
||||
@ -47,20 +46,6 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
9533716E237070B3003F1AF4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 958505A92364D36400BCB4A3;
|
||||
remoteInfo = Cloverhelper;
|
||||
};
|
||||
95337170237070BB003F1AF4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 958505A82364D36400BCB4A3;
|
||||
remoteInfo = Cloverhelper;
|
||||
};
|
||||
9542ABBC2373780C00DC03E6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9542ABB82373780C00DC03E6 /* boot1-inst.xcodeproj */;
|
||||
@ -143,7 +128,6 @@
|
||||
95509171238B1E3A00933A7E /* daemonInstaller in Copy tools */,
|
||||
9546AE1B23806299007155A6 /* CloverLogOut in Copy tools */,
|
||||
9542ABC02373783400DC03E6 /* boot1-install in Copy tools */,
|
||||
95337172237070CD003F1AF4 /* Cloverhelper in Copy tools */,
|
||||
9552D748236F33CA00C93377 /* CloverDaemonNew in Copy tools */,
|
||||
);
|
||||
name = "Copy tools";
|
||||
@ -322,7 +306,6 @@
|
||||
9569EC8C238DD7C6003AD72C /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Settings.strings; sourceTree = "<group>"; };
|
||||
9569EC8E238DD7C8003AD72C /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Settings.strings; sourceTree = "<group>"; };
|
||||
9569EC90238DD7CA003AD72C /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Settings.strings; sourceTree = "<group>"; };
|
||||
958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Cloverhelper.xcodeproj; path = cloverhelper/Cloverhelper.xcodeproj; sourceTree = "<group>"; };
|
||||
958861D9235F75FB00B64173 /* Driver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Driver.swift; sourceTree = "<group>"; };
|
||||
95C515212369BAF500E4A3A8 /* NVRAM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NVRAM.swift; sourceTree = "<group>"; };
|
||||
95C5152E236A0A7400E4A3A8 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
@ -356,14 +339,6 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
9533716B237070B3003F1AF4 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9533716F237070B3003F1AF4 /* Cloverhelper */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9542ABB92373780C00DC03E6 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -428,7 +403,6 @@
|
||||
95E68AC8235B862F002B37A5 /* Clover */,
|
||||
95524B83238051F3005F6425 /* CloverLogOut.xcodeproj */,
|
||||
9542ABB82373780C00DC03E6 /* boot1-inst.xcodeproj */,
|
||||
958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */,
|
||||
95C51577236B21AE00E4A3A8 /* CloverRunAtLogin.xcodeproj */,
|
||||
9552D740236F33A700C93377 /* CloverDaemonNew.xcodeproj */,
|
||||
95509169238B1DFA00933A7E /* daemonInstaller.xcodeproj */,
|
||||
@ -514,7 +488,6 @@
|
||||
dependencies = (
|
||||
95509170238B1E1C00933A7E /* PBXTargetDependency */,
|
||||
9546AE1923806286007155A6 /* PBXTargetDependency */,
|
||||
95337171237070BB003F1AF4 /* PBXTargetDependency */,
|
||||
9552D747236F33B900C93377 /* PBXTargetDependency */,
|
||||
9542ABBF2373781300DC03E6 /* PBXTargetDependency */,
|
||||
95C5157E236B21D400E4A3A8 /* PBXTargetDependency */,
|
||||
@ -597,10 +570,6 @@
|
||||
ProductGroup = 9552D741236F33A700C93377 /* Products */;
|
||||
ProjectRef = 9552D740236F33A700C93377 /* CloverDaemonNew.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 9533716B237070B3003F1AF4 /* Products */;
|
||||
ProjectRef = 958505B4236594C000BCB4A3 /* Cloverhelper.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 95524B84238051F3005F6425 /* Products */;
|
||||
ProjectRef = 95524B83238051F3005F6425 /* CloverLogOut.xcodeproj */;
|
||||
@ -622,13 +591,6 @@
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
9533716F237070B3003F1AF4 /* Cloverhelper */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = "compiled.mach-o.executable";
|
||||
path = Cloverhelper;
|
||||
remoteRef = 9533716E237070B3003F1AF4 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
9542ABBD2373780C00DC03E6 /* boot1-install */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = "compiled.mach-o.executable";
|
||||
@ -753,11 +715,6 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
95337171237070BB003F1AF4 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Cloverhelper;
|
||||
targetProxy = 95337170237070BB003F1AF4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
9542ABBF2373781300DC03E6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "boot1-install";
|
||||
@ -1064,7 +1021,7 @@
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1.13;
|
||||
CURRENT_PROJECT_VERSION = 1.14;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Clover/Frameworks",
|
||||
@ -1080,7 +1037,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Clover/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.13;
|
||||
MARKETING_VERSION = 1.14;
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@ -1100,7 +1057,7 @@
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1.13;
|
||||
CURRENT_PROJECT_VERSION = 1.14;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Clover/Frameworks",
|
||||
@ -1115,7 +1072,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Clover/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.13;
|
||||
MARKETING_VERSION = 1.14;
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.slice.Clover;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -803,7 +803,10 @@ class InstallerViewController: NSViewController {
|
||||
let supportedFS = ["exfat", "fat32", "hfs"]
|
||||
if !supportedFS.contains(filesystem) {
|
||||
NSSound.beep()
|
||||
post(text: "Error: can't install on \(filesystem.uppercased()) filesystem.", add: false, color: nil, scroll: false)
|
||||
post(text: "Error: can't install on \(filesystem.uppercased()) filesystem.",
|
||||
add: false,
|
||||
color: nil,
|
||||
scroll: false)
|
||||
return
|
||||
}
|
||||
AppSD.isInstalling = true
|
||||
@ -922,7 +925,6 @@ class InstallerViewController: NSViewController {
|
||||
if settingDict.write(toFile: "/tmp/Cloverapp", atomically: false) {
|
||||
AppSD.isInstalling = true
|
||||
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.spinner.startAnimation(nil)
|
||||
self.installButton.isEnabled = false
|
||||
@ -935,8 +937,8 @@ class InstallerViewController: NSViewController {
|
||||
|
||||
let task = Process()
|
||||
let msg = "Install Clover".locale
|
||||
let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("Cloverhelper")
|
||||
let script = "do shell script \"'\(helperPath)'\" with prompt \"\(msg)\" with administrator privileges"
|
||||
let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("CloverDaemonNew")
|
||||
let script = "do shell script \"'\(helperPath)' --CLOVER\" with prompt \"\(msg)\" with administrator privileges"
|
||||
task.launchPath = "/usr/bin/osascript"
|
||||
task.arguments = ["-e", script]
|
||||
let pipe: Pipe = Pipe()
|
||||
|
@ -850,9 +850,9 @@ class InstallerOutViewController: NSViewController {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 6.0) {
|
||||
self.view.window?.level = .normal
|
||||
}
|
||||
let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("Cloverhelper")
|
||||
let helperPath = Bundle.main.executablePath!.deletingLastPath.addPath("CloverDaemonNew")
|
||||
|
||||
let script = "do shell script \"'\(helperPath)'\" with administrator privileges"
|
||||
let script = "do shell script \"'\(helperPath)' --CLOVER\" with administrator privileges"
|
||||
var err : NSDictionary? = nil
|
||||
let result : NSAppleEventDescriptor = NSAppleScript(source: script)!.executeAndReturnError(&err)
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
954FF20E2371B13C00C3D94C /* DiskArbitration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954FF20D2371B13C00C3D94C /* DiskArbitration.framework */; };
|
||||
954FF2102371B16300C3D94C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954FF20F2371B16300C3D94C /* IOKit.framework */; };
|
||||
956034F623B7185B00E138D9 /* IO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956034F523B7185A00E138D9 /* IO.swift */; };
|
||||
95620BCD23BF71A500CCBFB2 /* BootInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */; };
|
||||
95A9A87E23B63F570060F1CA /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A9A87D23B63F570060F1CA /* Constants.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -28,6 +29,7 @@
|
||||
954FF20D2371B13C00C3D94C /* DiskArbitration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiskArbitration.framework; path = System/Library/Frameworks/DiskArbitration.framework; sourceTree = SDKROOT; };
|
||||
954FF20F2371B16300C3D94C /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
||||
956034F523B7185A00E138D9 /* IO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IO.swift; path = ../../Clover/IO.swift; sourceTree = "<group>"; };
|
||||
95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BootInstaller.swift; sourceTree = "<group>"; };
|
||||
95A9A87D23B63F570060F1CA /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -71,6 +73,7 @@
|
||||
953B8DEF2370BB5C007E36E3 /* NVRAM.swift */,
|
||||
953B8DED2370BB1A007E36E3 /* bdmesg.swift */,
|
||||
953B8DF12370BF5A007E36E3 /* Extensions.swift */,
|
||||
95620BCC23BF71A500CCBFB2 /* BootInstaller.swift */,
|
||||
);
|
||||
path = CloverDaemonNew;
|
||||
sourceTree = "<group>";
|
||||
@ -142,6 +145,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
95620BCD23BF71A500CCBFB2 /* BootInstaller.swift in Sources */,
|
||||
953B8DF22370BF5B007E36E3 /* Extensions.swift in Sources */,
|
||||
953D98872377094A003B369E /* Disks.swift in Sources */,
|
||||
953DBFDF236F037400B0C4FB /* main.swift in Sources */,
|
||||
|
605
CloverApp/CloverDaemonNew/CloverDaemonNew/BootInstaller.swift
Normal file
605
CloverApp/CloverDaemonNew/CloverDaemonNew/BootInstaller.swift
Normal file
@ -0,0 +1,605 @@
|
||||
//
|
||||
// BootInstaller.swift
|
||||
// CloverDaemonNew
|
||||
//
|
||||
// Created by vector sigma on 03/01/2020.
|
||||
// Copyright © 2020 CloverHackyColor. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class Installer: NSObject {
|
||||
let ktempLogPath = "/tmp/cltmplog"
|
||||
private var realTime : Bool = true
|
||||
private var gTargetVolume : String? = nil
|
||||
|
||||
public var realTimeOutPut:Bool {
|
||||
get {
|
||||
return self.realTime
|
||||
}
|
||||
set {
|
||||
self.realTime = newValue
|
||||
}
|
||||
}
|
||||
|
||||
private func cleanUp() {
|
||||
let t = Process()
|
||||
t.environment = ProcessInfo().environment
|
||||
if #available(OSX 10.13, *) {
|
||||
t.executableURL = URL(fileURLWithPath: "/bin/bash")
|
||||
} else {
|
||||
t.launchPath = "/bin/bash"
|
||||
}
|
||||
t.arguments = ["-c", "rm -f /tmp/Clover* && rm -f /tmp/boot0* && rm -f /tmp/boot1*"]
|
||||
t.launch()
|
||||
}
|
||||
|
||||
private func saveLog() {
|
||||
if (self.gTargetVolume != nil)
|
||||
&& fm.fileExists(atPath: self.gTargetVolume!)
|
||||
&& fm.fileExists(atPath: ktempLogPath) {
|
||||
let finalLogPath = self.gTargetVolume!.addPath("EFI/CLOVER/Clover.app_install.log")
|
||||
do {
|
||||
let data = try Data(contentsOf: URL(fileURLWithPath: finalLogPath))
|
||||
(data as NSData).write(toFile: finalLogPath, atomically: false)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func addToLog(_ str: String) {
|
||||
let output : String = str.hasSuffix("\n") ? str : "\n\(str)"
|
||||
if let data = output.data(using: .utf8) {
|
||||
if fm.fileExists(atPath: ktempLogPath) {
|
||||
if let fh = try? FileHandle(forWritingTo: URL(fileURLWithPath: ktempLogPath)) {
|
||||
fh.seekToEndOfFile()
|
||||
fh.write(data)
|
||||
fh.closeFile()
|
||||
}
|
||||
} else {
|
||||
(data as NSData).write(toFile: ktempLogPath, atomically: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func log(_ msg: String) {
|
||||
self.addToLog(msg)
|
||||
print(msg)
|
||||
}
|
||||
|
||||
private func exit(_ msg: String) {
|
||||
print(msg)
|
||||
self.addToLog(msg)
|
||||
self.saveLog()
|
||||
self.cleanUp()
|
||||
Darwin.exit(EXIT_FAILURE)
|
||||
}
|
||||
|
||||
private func copyReplace(src: String, dst: String, attr: [FileAttributeKey: Any]?, log: Bool) -> Bool {
|
||||
var attributes : [FileAttributeKey: Any]? = attr
|
||||
let upperDir = dst.deletingLastPath
|
||||
if log {
|
||||
if upperDir == "/" {
|
||||
self.log("+ \(dst)")
|
||||
} else {
|
||||
self.log("+ ../\(upperDir.lastPath)/\(dst.lastPath)")
|
||||
}
|
||||
}
|
||||
|
||||
if !fm.fileExists(atPath: src) {
|
||||
self.log("Error: \(src) doesn't exist.")
|
||||
return false
|
||||
}
|
||||
|
||||
// if attr is nil take attributes from source
|
||||
if attr == nil {
|
||||
do {
|
||||
attributes = try fm.attributesOfItem(atPath: src)
|
||||
} catch {
|
||||
print("Warning: can't get attributes from '\(src)'")
|
||||
}
|
||||
}
|
||||
|
||||
// remove destination if already exist
|
||||
if fm.fileExists(atPath: dst) {
|
||||
do {
|
||||
try fm.removeItem(atPath: dst)
|
||||
} catch {
|
||||
print(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// create upper directory if needed
|
||||
if !fm.fileExists(atPath: upperDir) {
|
||||
do {
|
||||
try fm.createDirectory(atPath: upperDir,
|
||||
withIntermediateDirectories: true,
|
||||
attributes: attributes)
|
||||
} catch {
|
||||
print(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// copy file to destination
|
||||
do {
|
||||
try fm.copyItem(atPath: src, toPath: dst)
|
||||
} catch {
|
||||
print(error)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private func createDirectory(at path: String, attr: [FileAttributeKey: Any]?, exitOnError: Bool) {
|
||||
var isDir : ObjCBool = false
|
||||
if fm.fileExists(atPath: path, isDirectory: &isDir) {
|
||||
if isDir.boolValue {
|
||||
return
|
||||
} else {
|
||||
do {
|
||||
try fm.removeItem(atPath: path)
|
||||
} catch {
|
||||
exit("\(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
try fm.createDirectory(atPath: path,
|
||||
withIntermediateDirectories: true,
|
||||
attributes: attr)
|
||||
} catch {
|
||||
exit("\(error)")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Install
|
||||
func install() {
|
||||
|
||||
let df = DateFormatter()
|
||||
df.locale = Locale(identifier: "en_US")
|
||||
df.dateFormat = "yyyy-MM-dd hh:mm:ss"
|
||||
let now = df.string(from: Date())
|
||||
|
||||
if fm.fileExists(atPath: ktempLogPath) {
|
||||
try? fm.removeItem(atPath: ktempLogPath)
|
||||
}
|
||||
|
||||
guard let CloverappDict = NSDictionary(contentsOfFile: "/tmp/Cloverapp") as? [String:AnyObject] else {
|
||||
exit("Error: can't load Cloverapp dictionary.")
|
||||
return // make the compiler happy
|
||||
}
|
||||
cleanUp()
|
||||
|
||||
let bootSectorsInstall = "/tmp/bootsectors-install"
|
||||
|
||||
let targetVol = CloverappDict["targetVol"] as! String
|
||||
let disk = CloverappDict["disk"] as! String
|
||||
let filesystem = CloverappDict["filesystem"] as! String
|
||||
let shemeMap = CloverappDict["shemeMap"] as! String
|
||||
let boot0 = CloverappDict["boot0"] as? String
|
||||
let boot1 = CloverappDict["boot1"] as? String
|
||||
let boot2 = CloverappDict["boot2"] as? String
|
||||
let CloverV2 = CloverappDict["CloverV2"] as! String
|
||||
let boot1installPath = CloverappDict["boot1install"] as? String
|
||||
let bootSectorsInstallSrc = CloverappDict["bootsectors-install"] as? String
|
||||
let backUpPath = CloverappDict["BackUpPath"] as? String
|
||||
let version = CloverappDict["version"] as! String
|
||||
let isESP = (CloverappDict["isESP"] as! NSNumber).boolValue
|
||||
|
||||
let alt : Bool = (CloverappDict["alt"] as? NSNumber)?.boolValue ?? false
|
||||
|
||||
log("\(version) (v\(daemonVersion)), \(now)")
|
||||
log("SELF = \(CommandLine.arguments[0])")
|
||||
if geteuid() != 0 {
|
||||
exit("Error: you don't have root permissions.")
|
||||
}
|
||||
|
||||
|
||||
if (backUpPath != nil) {
|
||||
log("Backup made at:\n\(backUpPath!).")
|
||||
}
|
||||
|
||||
if fm.fileExists(atPath: bootSectorsInstall) {
|
||||
do {
|
||||
try fm.removeItem(atPath: bootSectorsInstall)
|
||||
} catch {
|
||||
exit("Error: can't remove old bootsectors-install.")
|
||||
}
|
||||
}
|
||||
|
||||
if (bootSectorsInstallSrc != nil) {
|
||||
log("bootSectorsInstallSrc = \(bootSectorsInstallSrc!)")
|
||||
}
|
||||
|
||||
// MARK: Preferences dict init
|
||||
let preferences = NSMutableDictionary()
|
||||
|
||||
// MARK: Attributes init
|
||||
let attributes : [FileAttributeKey: Any] = [FileAttributeKey.posixPermissions: 0777]
|
||||
|
||||
// MARK: Check Volume
|
||||
|
||||
self.gTargetVolume = targetVol
|
||||
if !fm.fileExists(atPath: targetVol) {
|
||||
exit("Error: target volume \"\(targetVol)\" doesn't exist.")
|
||||
}
|
||||
|
||||
if !fm.fileExists(atPath: CloverV2) {
|
||||
exit("Error: cannot found CloverV2 directory.")
|
||||
}
|
||||
|
||||
log("Target volume: \(targetVol)")
|
||||
|
||||
if !fm.isWritableFile(atPath: targetVol) {
|
||||
exit("Error: target volume \"\(targetVol)\" is not writable.")
|
||||
}
|
||||
|
||||
// MARK: Check paths
|
||||
var boot0Path: String? = nil
|
||||
var boot1Path: String? = nil
|
||||
var boot2Path: String? = nil
|
||||
if (boot0 != nil) {
|
||||
log("boot0: \(boot0!)")
|
||||
preferences.setValue(boot0!, forKey: "boot0")
|
||||
boot0Path = CloverV2.addPath("BootSectors").addPath(boot0!)
|
||||
if !fm.fileExists(atPath: boot0Path!) {
|
||||
exit("Error: cannot found \"\(boot0!)\".")
|
||||
}
|
||||
}
|
||||
|
||||
if (boot1 != nil) {
|
||||
log("boot1: \(boot1!)")
|
||||
boot1Path = CloverV2.addPath("BootSectors").addPath(boot1!)
|
||||
if !fm.fileExists(atPath: boot1Path!) {
|
||||
exit("Error: cannot found \"\(boot1!)\".")
|
||||
}
|
||||
}
|
||||
|
||||
if (boot2 != nil) {
|
||||
log("boot2: \(boot2!)")
|
||||
preferences.setValue(boot2!, forKey: "boot2")
|
||||
boot2Path = CloverV2.addPath("Bootloaders/x64").addPath(boot2!)
|
||||
if !fm.fileExists(atPath: boot2Path!) {
|
||||
exit("Error: cannot found \"\(boot2!)\".")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Create Directories
|
||||
createDirectory(at: targetVol.addPath("EFI/CLOVER"), attr: attributes, exitOnError: true)
|
||||
createDirectory(at: targetVol.addPath("EFI/BOOT"), attr: attributes, exitOnError: true)
|
||||
createDirectory(at: targetVol.addPath("EFI/CLOVER/misc"), attr: attributes, exitOnError: true)
|
||||
|
||||
let subDirs = ["ACPI/origin",
|
||||
"ACPI/patched",
|
||||
"ACPI/WINDOWS",
|
||||
"kexts/10",
|
||||
"kexts/10_recovery",
|
||||
"kexts/10_installer",
|
||||
"kexts/10.11",
|
||||
"kexts/10.12",
|
||||
"kexts/10.13",
|
||||
"kexts/10.14",
|
||||
"kexts/10.15",
|
||||
"kexts/Other",
|
||||
"ROM"]
|
||||
|
||||
for dir in subDirs {
|
||||
createDirectory(at: targetVol.addPath("EFI/CLOVER").addPath(dir),
|
||||
attr: attributes,
|
||||
exitOnError: true)
|
||||
|
||||
|
||||
}
|
||||
|
||||
for dir in subDirs {
|
||||
if !fm.fileExists(atPath: targetVol.addPath("EFI/CLOVER/OEM")) {
|
||||
createDirectory(at: targetVol.addPath("EFI/CLOVER/OEM/SystemProductName").addPath(dir),
|
||||
attr: attributes,
|
||||
exitOnError: true)
|
||||
|
||||
if dir != "ROM" {
|
||||
createDirectory(at: targetVol.addPath("EFI/CLOVER/OEM/SystemProductName/UEFI").addPath(dir),
|
||||
attr: attributes,
|
||||
exitOnError: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Install Clover and drivers
|
||||
self.log("\nInstalling/Updating Clover:")
|
||||
if !copyReplace(src: CloverV2.addPath("EFI/BOOT/BOOTX64.efi"),
|
||||
dst: targetVol.addPath("EFI/BOOT/BOOTX64.efi"),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy BOOTX64.efi to destination.")
|
||||
}
|
||||
|
||||
if !copyReplace(src: CloverV2.addPath("EFI/CLOVER/CLOVERX64.efi"),
|
||||
dst: targetVol.addPath("EFI/CLOVER/CLOVERX64.efi"),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy CLOVERX64.efi to destination.")
|
||||
}
|
||||
|
||||
self.log("\nInstalling/Updating drivers:")
|
||||
if let toDelete = CloverappDict["toDelete"] as? [String] {
|
||||
for dpath in toDelete {
|
||||
if fm.fileExists(atPath: dpath) {
|
||||
self.log("- ../\(dpath.deletingLastPath.lastPath)/\(dpath.lastPath)")
|
||||
do {
|
||||
try fm.removeItem(atPath: dpath)
|
||||
} catch {
|
||||
exit("\(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let UEFIdest = targetVol.addPath("EFI/CLOVER/drivers/UEFI")
|
||||
let BIOSdest = targetVol.addPath("EFI/CLOVER/drivers/BIOS")
|
||||
if let UEFI = CloverappDict["UEFI"] as? [String] {
|
||||
for dpath in UEFI {
|
||||
if !copyReplace(src: dpath,
|
||||
dst: UEFIdest.addPath(dpath.lastPath),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy '\(dpath)' to destination.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let BIOS = CloverappDict["BIOS"] as? [String] {
|
||||
for dpath in BIOS {
|
||||
if !copyReplace(src: dpath,
|
||||
dst: BIOSdest.addPath(dpath.lastPath),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy '\(dpath)' to destination.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Install tools
|
||||
let cv2tools = CloverV2.addPath("EFI/CLOVER/tools")
|
||||
if fm.fileExists(atPath: cv2tools) {
|
||||
self.log("\nInstalling/Updating tools:")
|
||||
var tools : [String] = [String]()
|
||||
do {
|
||||
tools = try fm.contentsOfDirectory(atPath: cv2tools)
|
||||
} catch { }
|
||||
|
||||
for t in tools {
|
||||
if t.fileExtension == "efi" {
|
||||
if !copyReplace(src: cv2tools.addPath(t),
|
||||
dst: targetVol.addPath("EFI/CLOVER/tools").addPath(t),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy '\(cv2tools.addPath(t))' to destination.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Install docs
|
||||
let cv2docs = CloverV2.addPath("EFI/CLOVER/doc")
|
||||
if fm.fileExists(atPath: cv2docs) {
|
||||
self.log("\nInstalling/Updating docs:")
|
||||
var docs : [String] = [String]()
|
||||
do {
|
||||
docs = try fm.contentsOfDirectory(atPath: cv2docs)
|
||||
} catch { }
|
||||
|
||||
for d in docs {
|
||||
if d.fileExtension == "efi" {
|
||||
var a : [FileAttributeKey: Any]? = nil
|
||||
do {
|
||||
a = try fm.attributesOfItem(atPath: cv2docs.addPath(d))
|
||||
} catch { }
|
||||
if !copyReplace(src: cv2docs.addPath(d),
|
||||
dst: targetVol.addPath("EFI/CLOVER/doc").addPath(d),
|
||||
attr: a,
|
||||
log: true) {
|
||||
// do not fail the installation fro a document. So just log:
|
||||
self.log("Error: cannot copy '\(cv2tools.addPath(d))' to destination.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Create config.plist
|
||||
let configPath = targetVol.addPath("EFI/CLOVER/config.plist")
|
||||
let configSamplePath = CloverV2.addPath("EFI/CLOVER/config-sample.plist")
|
||||
if !fm.fileExists(atPath: configPath) {
|
||||
if !copyReplace(src: configSamplePath,
|
||||
dst: configPath,
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
self.log("Error: cannot copy '\(configSamplePath)' to destination.")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Install theme
|
||||
// install the theme defined in config.plist
|
||||
// Also do nothing if the theme directory already exist
|
||||
// as Clover is already installed and user as its own free will,
|
||||
// even to run w/o a theme
|
||||
if let config = NSDictionary(contentsOfFile: configPath) {
|
||||
let themesSourceDir = CloverV2.addPath("themespkg")
|
||||
let themesDestDir = targetVol.addPath("EFI/CLOVER/themes")
|
||||
if !fm.fileExists(atPath: themesDestDir) {
|
||||
if let GUI = config.object(forKey: "GUI") as? NSDictionary {
|
||||
if let Theme = GUI.object(forKey: "Theme") as? String {
|
||||
if fm.fileExists(atPath: themesSourceDir.addPath(Theme)) {
|
||||
self.log("\nInstalling Theme \"\(Theme)\":")
|
||||
if !copyReplace(src: themesSourceDir.addPath(Theme),
|
||||
dst: themesDestDir.addPath(Theme),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
// do not fail for a theme, just log:
|
||||
self.log("Error: cannot copy '\(themesSourceDir.addPath(Theme))' to destination.")
|
||||
}
|
||||
} else {
|
||||
self.log("Warning: cannot found Theme '\(Theme)' defined in config.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.log("Warning: cannot read '\(configPath)' into a valid Dictionary.")
|
||||
}
|
||||
|
||||
// MARK: Stage 2 Installation
|
||||
if boot2Path != nil {
|
||||
self.log("\nInstalling stage 2..")
|
||||
if !copyReplace(src: boot2Path!,
|
||||
dst: targetVol.addPath("boot"),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
self.log("Error: cannot copy '\(boot2Path!)' to destination.")
|
||||
}
|
||||
|
||||
if alt {
|
||||
preferences.setValue(true, forKey: "boot2Alt")
|
||||
let bootX64path = CloverV2.addPath("Bootloaders/x64")
|
||||
var loaders : [String] = [String]()
|
||||
do {
|
||||
loaders = try fm.contentsOfDirectory(atPath: bootX64path)
|
||||
} catch { }
|
||||
|
||||
for boot in loaders {
|
||||
if boot.hasPrefix("boot") {
|
||||
self.log("\nInstalling stage 2 \"\(boot) (alt)\".")
|
||||
if !copyReplace(src: bootX64path.addPath(boot),
|
||||
dst: targetVol.addPath(boot),
|
||||
attr: attributes,
|
||||
log: true) {
|
||||
exit("Error: cannot copy '\(bootX64path.addPath(boot))' to destination.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------- end stage 2
|
||||
}
|
||||
|
||||
// MARK: Write Preferences
|
||||
preferences.write(toFile: targetVol.addPath("EFI/CLOVER/pref.plist"), atomically: true)
|
||||
try? fm.setAttributes(attributes, ofItemAtPath: targetVol.addPath("EFI/CLOVER/pref.plist"))
|
||||
saveLog()
|
||||
|
||||
// MARK: Boot sectors installation
|
||||
if (boot0Path != nil && boot1Path != nil && bootSectorsInstallSrc != nil) {
|
||||
if !copyReplace(src: bootSectorsInstallSrc!,
|
||||
dst: bootSectorsInstall,
|
||||
attr: nil,
|
||||
log: false) {
|
||||
exit("Error: cannot copy '\(bootSectorsInstallSrc!)' to destination.")
|
||||
}
|
||||
|
||||
|
||||
if !copyReplace(src: boot0Path!,
|
||||
dst: "/tmp".addPath(boot0!),
|
||||
attr: nil,
|
||||
log: false) {
|
||||
exit("Error: cannot copy '\(boot0Path!)' to destination.")
|
||||
}
|
||||
|
||||
if !copyReplace(src: boot1Path!,
|
||||
dst: "/tmp".addPath(boot1!),
|
||||
attr: nil,
|
||||
log: false) {
|
||||
exit("Error: cannot copy '\(boot1Path!)' to destination.")
|
||||
}
|
||||
|
||||
if !copyReplace(src: boot1installPath!,
|
||||
dst: "/tmp/boot1-install",
|
||||
attr: nil,
|
||||
log: false) {
|
||||
exit("Error: cannot copy '\(boot1installPath!)' to destination.")
|
||||
}
|
||||
|
||||
let esp = isESP ? "ESP" : "OTHER"
|
||||
let task = Process()
|
||||
task.environment = ProcessInfo().environment
|
||||
if #available(OSX 10.13, *) {
|
||||
task.executableURL = URL(fileURLWithPath: bootSectorsInstall)
|
||||
} else {
|
||||
task.launchPath = bootSectorsInstall
|
||||
}
|
||||
task.arguments = [ disk, filesystem, shemeMap, boot0!, boot1!, esp ]
|
||||
let pipe = Pipe()
|
||||
|
||||
if self.realTime {
|
||||
task.standardOutput = pipe
|
||||
task.standardError = pipe
|
||||
let fh = pipe.fileHandleForReading
|
||||
fh.waitForDataInBackgroundAndNotify()
|
||||
|
||||
var op1 : NSObjectProtocol!
|
||||
op1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable,
|
||||
object: fh, queue: nil) {
|
||||
notification -> Void in
|
||||
let data = fh.availableData
|
||||
if data.count > 0 {
|
||||
let output = String(decoding: data, as: UTF8.self)
|
||||
self.log(output)
|
||||
fh.waitForDataInBackgroundAndNotify()
|
||||
} else {
|
||||
NotificationCenter.default.removeObserver(op1 as Any)
|
||||
}
|
||||
}
|
||||
|
||||
var op2 : NSObjectProtocol!
|
||||
op2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification,
|
||||
object: task, queue: nil) {
|
||||
notification -> Void in
|
||||
NotificationCenter.default.removeObserver(op2 as Any)
|
||||
if task.terminationStatus != 0 {
|
||||
self.exit("Error: failed installing boot sectors.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
} else {
|
||||
task.standardOutput = pipe
|
||||
task.standardError = pipe
|
||||
|
||||
let fh = pipe.fileHandleForReading
|
||||
task.terminationHandler = { (t) in
|
||||
if t.terminationStatus != 0 {
|
||||
self.exit("Error: failed installing boot sectors.")
|
||||
}
|
||||
}
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
|
||||
// TODO: make output in real time
|
||||
let data = fh.readDataToEndOfFile()
|
||||
if let out = String(data: data, encoding: .utf8) {
|
||||
self.log(out)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
saveLog()
|
||||
if (isESP) {
|
||||
let task = Process()
|
||||
task.environment = ProcessInfo().environment
|
||||
if #available(OSX 10.13, *) {
|
||||
task.executableURL = URL(fileURLWithPath: "/usr/sbin/diskutil")
|
||||
} else {
|
||||
task.launchPath = "/usr/sbin/diskutil"
|
||||
}
|
||||
task.arguments = [ "umount", "force", disk ]
|
||||
task.launch()
|
||||
}
|
||||
cleanUp()
|
||||
}
|
||||
Darwin.exit(EXIT_SUCCESS)
|
||||
// ------------- end
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
let daemonVersion = "1.0.9"
|
||||
let daemonVersion = "1.1.0"
|
||||
|
||||
let fm = FileManager.default
|
||||
|
||||
@ -435,7 +435,7 @@ func main() {
|
||||
exit(EXIT_SUCCESS)
|
||||
}
|
||||
sigtermSource.resume()
|
||||
|
||||
|
||||
RunLoop.current.run()
|
||||
//dispatchMain()
|
||||
}
|
||||
@ -443,7 +443,7 @@ func main() {
|
||||
let myPath = CommandLine.arguments[0]
|
||||
let myName = (myPath as NSString).lastPathComponent
|
||||
|
||||
if CommandLine.arguments.contains("--install") {
|
||||
if CommandLine.arguments[1] == "--install" {
|
||||
print("Installing daemon...")
|
||||
// build the launch daemon
|
||||
let launch = NSMutableDictionary()
|
||||
@ -520,7 +520,7 @@ if CommandLine.arguments.contains("--install") {
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
} else if CommandLine.arguments.contains("--uninstall") {
|
||||
} else if CommandLine.arguments[1] == "--uninstall" {
|
||||
print("uninstalling daemon...")
|
||||
do {
|
||||
if fm.fileExists(atPath: launchPlistPath) {
|
||||
@ -549,6 +549,11 @@ if CommandLine.arguments.contains("--install") {
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
} else if CommandLine.arguments[1] == "--CLOVER" {
|
||||
let installer = Installer()
|
||||
installer.realTimeOutPut = true
|
||||
installer.install()
|
||||
RunLoop.current.run()
|
||||
} else {
|
||||
main()
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Created by vector sigma on 04/11/2019.
|
||||
# Copyright © 2019 CloverHackyColor. All rights reserved.
|
||||
|
||||
logPath="/tmp/cltmplog"
|
||||
exec > >(tee -a $logPath) 2>&1
|
||||
# Created by vector sigma on 04/11/2019.
|
||||
# Copyright © 2019 CloverHackyColor. All rights reserved.
|
||||
|
||||
cd /tmp
|
||||
|
||||
|
@ -1,294 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
958505AD2364D36400BCB4A3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 958505AC2364D36400BCB4A3 /* main.m */; };
|
||||
95E61978236F87D100D20FCB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E61977236F87D100D20FCB /* Foundation.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
958505A72364D36400BCB4A3 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
958505A92364D36400BCB4A3 /* Cloverhelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Cloverhelper; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
958505AC2364D36400BCB4A3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
95E61977236F87D100D20FCB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
958505A62364D36400BCB4A3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
95E61978236F87D100D20FCB /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
958505A02364D36300BCB4A3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
958505AB2364D36400BCB4A3 /* Cloverhelper */,
|
||||
958505AA2364D36400BCB4A3 /* Products */,
|
||||
95E61976236F87D100D20FCB /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
958505AA2364D36400BCB4A3 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
958505A92364D36400BCB4A3 /* Cloverhelper */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
958505AB2364D36400BCB4A3 /* Cloverhelper */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
958505AC2364D36400BCB4A3 /* main.m */,
|
||||
);
|
||||
path = Cloverhelper;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
95E61976236F87D100D20FCB /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
95E61977236F87D100D20FCB /* Foundation.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
958505A82364D36400BCB4A3 /* Cloverhelper */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 958505B02364D36400BCB4A3 /* Build configuration list for PBXNativeTarget "Cloverhelper" */;
|
||||
buildPhases = (
|
||||
958505A52364D36400BCB4A3 /* Sources */,
|
||||
958505A62364D36400BCB4A3 /* Frameworks */,
|
||||
958505A72364D36400BCB4A3 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Cloverhelper;
|
||||
productName = cloverhelper;
|
||||
productReference = 958505A92364D36400BCB4A3 /* Cloverhelper */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
958505A12364D36300BCB4A3 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1130;
|
||||
ORGANIZATIONNAME = CloverHackyColor;
|
||||
TargetAttributes = {
|
||||
958505A82364D36400BCB4A3 = {
|
||||
CreatedOnToolsVersion = 11.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 958505A42364D36300BCB4A3 /* Build configuration list for PBXProject "Cloverhelper" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 958505A02364D36300BCB4A3;
|
||||
productRefGroup = 958505AA2364D36400BCB4A3 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
958505A82364D36400BCB4A3 /* Cloverhelper */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
958505A52364D36400BCB4A3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
958505AD2364D36400BCB4A3 /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
958505AE2364D36400BCB4A3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
958505AF2364D36400BCB4A3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
958505B12364D36400BCB4A3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
958505B22364D36400BCB4A3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
958505A42364D36300BCB4A3 /* Build configuration list for PBXProject "Cloverhelper" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
958505AE2364D36400BCB4A3 /* Debug */,
|
||||
958505AF2364D36400BCB4A3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
958505B02364D36400BCB4A3 /* Build configuration list for PBXNativeTarget "Cloverhelper" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
958505B12364D36400BCB4A3 /* Debug */,
|
||||
958505B22364D36400BCB4A3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 958505A12364D36300BCB4A3 /* Project object */;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:cloverhelper.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -1,540 +0,0 @@
|
||||
//
|
||||
// main.m
|
||||
// Cloverhelper
|
||||
//
|
||||
// Created by vector sigma on 26/10/2019.
|
||||
// Copyright © 2019 CloverHackyColor. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/*
|
||||
This command line must be run as root and it is responsible for creating the Clover tree
|
||||
and to install boot sectors and drivers.
|
||||
*/
|
||||
|
||||
// TODO: redone in swift as swift command line are now small in size, with no hurry...
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define ktempLogPath "/tmp/cltmplog"
|
||||
#define kfm [NSFileManager defaultManager]
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark copy and replace files
|
||||
#pragma mark -
|
||||
|
||||
void cleanUp() {
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
|
||||
[task setEnvironment:[[NSProcessInfo new] environment]];
|
||||
[task setLaunchPath:@"/bin/bash"];
|
||||
[task setArguments:@[ @"-c", @"rm -f /tmp/Clover* && rm -f /tmp/boot0* && rm -f /tmp/boot1*" ]];
|
||||
|
||||
[task launch];
|
||||
}
|
||||
|
||||
NSString *gTargetVolume;
|
||||
|
||||
void saveLog() {
|
||||
if (gTargetVolume != nil
|
||||
&& [kfm fileExistsAtPath:gTargetVolume]
|
||||
&& [kfm fileExistsAtPath:@ktempLogPath]) {
|
||||
NSString *finalLogPath =
|
||||
[gTargetVolume stringByAppendingPathComponent:@"EFI/CLOVER/Clover.app_install.log"];
|
||||
if ([kfm fileExistsAtPath: finalLogPath]) {
|
||||
[kfm removeItemAtPath:finalLogPath error:nil];
|
||||
}
|
||||
NSData *log = [NSData dataWithContentsOfFile:@ktempLogPath];
|
||||
if (log != nil) {
|
||||
[log writeToFile:finalLogPath atomically:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addToLog(NSString *str) {
|
||||
if (![kfm fileExistsAtPath:@ktempLogPath]) {
|
||||
system([[NSString stringWithFormat:@"echo > %s", ktempLogPath] UTF8String]);
|
||||
}
|
||||
NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:@ktempLogPath];
|
||||
[fh seekToEndOfFile];
|
||||
[fh writeData:[str dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[fh closeFile];
|
||||
}
|
||||
|
||||
void post(NSString *format, ...) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
NSString *str = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||
addToLog(str);
|
||||
va_end(arguments);
|
||||
printf("%s", [str UTF8String]);
|
||||
|
||||
}
|
||||
|
||||
void exitWithMessage(NSString *format, ...) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
NSString *str = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||
|
||||
va_end(arguments);
|
||||
printf("%s", [str UTF8String]);
|
||||
addToLog(str);
|
||||
saveLog();
|
||||
cleanUp();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
BOOL copyReplace(NSString *source, NSString *dest, NSDictionary *attributes) {
|
||||
NSError *err = nil;
|
||||
NSString *upperDir = [dest stringByDeletingLastPathComponent];
|
||||
|
||||
if ([upperDir isEqualToString:@"/"]) {
|
||||
post(@"+ ../%@\n", [dest lastPathComponent]);
|
||||
} else {
|
||||
post(@"+ ../%@/%@\n",
|
||||
[[dest stringByDeletingLastPathComponent] lastPathComponent], [dest lastPathComponent]);
|
||||
}
|
||||
|
||||
if (![kfm fileExistsAtPath:source]) {
|
||||
post(@"Error: %@ doesn't exist\n", source);
|
||||
return NO;
|
||||
}
|
||||
// remove destination if already exist
|
||||
if ([kfm fileExistsAtPath:dest]) {
|
||||
[kfm removeItemAtPath:dest error:&err];
|
||||
}
|
||||
|
||||
// create upper directory if needed
|
||||
if (err == nil) {
|
||||
if (![kfm fileExistsAtPath:upperDir]) {
|
||||
[kfm createDirectoryAtPath:upperDir
|
||||
withIntermediateDirectories:YES
|
||||
attributes:attributes
|
||||
error:&err];
|
||||
}
|
||||
}
|
||||
|
||||
// copy the new item
|
||||
if (err == nil) {
|
||||
if ([kfm copyItemAtPath:source toPath:dest error:&err] && attributes) {
|
||||
[kfm setAttributes:attributes ofItemAtPath:dest error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// print any errors if any
|
||||
if (err != nil) {
|
||||
post(@"%@\n", err.description);
|
||||
}
|
||||
|
||||
return (err == nil);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Main
|
||||
#pragma mark -
|
||||
|
||||
int main(int argc, char * const * argv) {
|
||||
@autoreleasepool {
|
||||
if ([kfm fileExistsAtPath:@ktempLogPath]) {
|
||||
[kfm removeItemAtPath:@ktempLogPath error:nil];
|
||||
}
|
||||
|
||||
NSDateFormatter * df = [NSDateFormatter new];
|
||||
[df setDateFormat:@"yyyy-MMM-dd HH:mm:ss"];
|
||||
NSLocale *locale = [[NSLocale alloc]
|
||||
initWithLocaleIdentifier:@"en_US"];
|
||||
[df setLocale:locale];
|
||||
NSString *dateString = [df stringFromDate:[NSDate new]];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
exitWithMessage(@"Error: you don't have root permissions\n");
|
||||
}
|
||||
|
||||
NSDictionary *CloverappDict = [NSDictionary dictionaryWithContentsOfFile:@"/tmp/Cloverapp"];
|
||||
if (CloverappDict == nil) {
|
||||
exitWithMessage(@"Error: can't load Cloverapp dictionary\n");
|
||||
}
|
||||
cleanUp();
|
||||
|
||||
NSString *bootSectorsInstall = @"/tmp/bootsectors-install";
|
||||
|
||||
NSString *targetVol = [CloverappDict objectForKey:@"targetVol"];
|
||||
NSString *disk = [CloverappDict objectForKey:@"disk"];
|
||||
NSString *filesystem = [CloverappDict objectForKey:@"filesystem"];
|
||||
NSString *shemeMap = [CloverappDict objectForKey:@"shemeMap"];
|
||||
NSString *boot0 = [CloverappDict objectForKey:@"boot0"];
|
||||
NSString *boot1 = [CloverappDict objectForKey:@"boot1"];
|
||||
NSString *boot2 = [CloverappDict objectForKey:@"boot2"];
|
||||
NSString *cloverv2 = [CloverappDict objectForKey:@"CloverV2"];
|
||||
NSString *boot1installPath = [CloverappDict objectForKey:@"boot1install"];
|
||||
NSString *bootSectorsInstallSrc = [CloverappDict objectForKey:@"bootsectors-install"];
|
||||
NSString *backUpPath = [CloverappDict objectForKey:@"BackUpPath"];
|
||||
NSString *version = [CloverappDict objectForKey:@"version"];
|
||||
BOOL isESP = [[CloverappDict objectForKey:@"isESP"] boolValue];
|
||||
|
||||
post(@"%@, %@\n\n", version, dateString);
|
||||
post(@"My Path = %s\n", argv[0]);
|
||||
if (backUpPath != nil) {
|
||||
post(@"Backup made at:\n%@.\n", backUpPath);
|
||||
}
|
||||
|
||||
if ([kfm fileExistsAtPath:bootSectorsInstall]) {
|
||||
post(@"Note: found old bootsectors-install..removing it..\n");
|
||||
if (![kfm removeItemAtPath:bootSectorsInstall error:nil]) {
|
||||
exitWithMessage(@"Error: can't remove old bootsectors-install.");
|
||||
}
|
||||
}
|
||||
|
||||
if (bootSectorsInstallSrc != nil) {
|
||||
post(@"bootSectorsInstallSrc = %@\n", bootSectorsInstallSrc);
|
||||
}
|
||||
|
||||
BOOL alt = NO;
|
||||
if ([CloverappDict objectForKey:@"alt"] != nil) {
|
||||
alt = [[CloverappDict objectForKey:@"alt"] boolValue];
|
||||
}
|
||||
|
||||
#pragma mark Preferences dict init
|
||||
NSMutableDictionary *preferences = [NSMutableDictionary new];
|
||||
|
||||
#pragma mark Attributes init
|
||||
NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithShort:0777], NSFilePosixPermissions, nil];
|
||||
#pragma mark Check Volume
|
||||
BOOL isDir = NO;
|
||||
|
||||
if (targetVol == nil) {
|
||||
exitWithMessage(@"Error: option targetVol [path to volume] not specified\n");
|
||||
}
|
||||
gTargetVolume = targetVol;
|
||||
|
||||
if (![kfm fileExistsAtPath:targetVol]) {
|
||||
exitWithMessage(@"Error: target volume \"%@\" doesn't exist.\n", targetVol);
|
||||
}
|
||||
|
||||
if (cloverv2 == nil || ![kfm fileExistsAtPath:cloverv2]) {
|
||||
exitWithMessage(@"Error: cannot found CloverV2 directory\n");
|
||||
}
|
||||
|
||||
post(@"Target volume: %@\n", targetVol);
|
||||
/*
|
||||
// check if target volume is writable
|
||||
NSString *volEnds = targetVol;
|
||||
if (![volEnds hasSuffix:@"/"]) {
|
||||
volEnds = [targetVol stringByAppendingString:@"/"];
|
||||
}
|
||||
|
||||
|
||||
if (![kfm isWritableFileAtPath:volEnds]) {
|
||||
exitWithMessage(@"Error: target volume \"%@\" is not writable.\n", targetVol);
|
||||
}
|
||||
*/
|
||||
#pragma mark Check paths
|
||||
// check other options before proceed
|
||||
NSString *boot0Path = nil, *boot1Path = nil, *boot2Path = nil;
|
||||
if (boot0 != nil) {
|
||||
post(@"boot0: %@\n", boot0);
|
||||
[preferences setValue:boot0 forKey:@"boot0"];
|
||||
boot0Path = [[cloverv2 stringByAppendingPathComponent:@"BootSectors"] stringByAppendingPathComponent:boot0];
|
||||
if (![kfm fileExistsAtPath:boot0Path]) {
|
||||
exitWithMessage(@"Error: cannot found \"%@\".\n", boot0);
|
||||
}
|
||||
}
|
||||
|
||||
if (boot1 != nil) {
|
||||
post(@"boot1: %@\n", boot1);
|
||||
boot1Path = [[cloverv2 stringByAppendingPathComponent:@"BootSectors"] stringByAppendingPathComponent:boot1];
|
||||
if (![kfm fileExistsAtPath:boot1Path]) {
|
||||
exitWithMessage(@"Error: cannot found \"%@\".\n", boot1);
|
||||
}
|
||||
}
|
||||
|
||||
if (boot2 != nil) {
|
||||
post(@"boot2: %@\n", boot2);
|
||||
[preferences setValue:boot2 forKey:@"boot2"];
|
||||
boot2Path = [[cloverv2 stringByAppendingPathComponent:@"Bootloaders/x64"] stringByAppendingPathComponent:boot2];
|
||||
if (![kfm fileExistsAtPath:boot2Path]) {
|
||||
exitWithMessage(@"Error: cannot found \"%@\".\n", boot2);
|
||||
}
|
||||
}
|
||||
|
||||
NSError *err = nil;
|
||||
if ([kfm fileExistsAtPath:
|
||||
[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"] isDirectory:&isDir]) {
|
||||
if (!isDir) {
|
||||
[kfm removeItemAtPath:
|
||||
[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"] error:&err];
|
||||
}
|
||||
}
|
||||
|
||||
if (![kfm fileExistsAtPath:[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"]]) {
|
||||
[kfm createDirectoryAtPath:[targetVol stringByAppendingPathComponent:@"EFI/CLOVER"]
|
||||
withIntermediateDirectories:YES
|
||||
attributes:attributes
|
||||
error:&err];
|
||||
}
|
||||
|
||||
if (err != nil) {
|
||||
exitWithMessage(@"%@\n", err.description);
|
||||
}
|
||||
|
||||
#pragma mark Create directories
|
||||
NSArray *sub = [NSArray arrayWithObjects:
|
||||
@"EFI/BOOT",
|
||||
@"EFI/CLOVER/ACPI/origin",
|
||||
@"EFI/CLOVER/ACPI/patched",
|
||||
@"EFI/CLOVER/ACPI/WINDOWS",
|
||||
@"EFI/CLOVER/kexts/10",
|
||||
@"EFI/CLOVER/kexts/10_recovery",
|
||||
@"EFI/CLOVER/kexts/10_installer",
|
||||
@"EFI/CLOVER/kexts/10.11",
|
||||
@"EFI/CLOVER/kexts/10.12",
|
||||
@"EFI/CLOVER/kexts/10.13",
|
||||
@"EFI/CLOVER/kexts/10.14",
|
||||
@"EFI/CLOVER/kexts/10.15",
|
||||
@"EFI/CLOVER/kexts/Other",
|
||||
@"EFI/CLOVER/misc",
|
||||
@"EFI/CLOVER/ROM",
|
||||
nil];
|
||||
|
||||
for (int i = 0; i < [sub count]; i++) {
|
||||
err = nil;
|
||||
NSString *fp = [targetVol stringByAppendingPathComponent:[sub objectAtIndex:i]];
|
||||
if (![kfm fileExistsAtPath:fp]) {
|
||||
[kfm createDirectoryAtPath:fp withIntermediateDirectories:YES attributes:attributes error:&err];
|
||||
if (err != nil) {
|
||||
exitWithMessage(@"%@\n", err.description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Install Clover and drivers
|
||||
post(@"\nInstalling/Updating Clover:\n");
|
||||
if (!copyReplace([cloverv2 stringByAppendingPathComponent:@"EFI/BOOT/BOOTX64.efi"],
|
||||
[targetVol stringByAppendingPathComponent:@"EFI/BOOT/BOOTX64.efi"],
|
||||
attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy BOOTX64.efi to destination.\n");
|
||||
}
|
||||
|
||||
if (!copyReplace([cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/CLOVERX64.efi"],
|
||||
[targetVol stringByAppendingPathComponent:@"EFI/CLOVER/CLOVERX64.efi"],
|
||||
attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy CLOVERX64.efi to destination.\n");
|
||||
}
|
||||
|
||||
post(@"\nInstalling/Updating drivers:\n");
|
||||
NSArray * toDelete = [CloverappDict objectForKey:@"toDelete"];
|
||||
NSArray * UEFI = [CloverappDict objectForKey:@"UEFI"];
|
||||
NSArray * BIOS = [CloverappDict objectForKey:@"BIOS"];
|
||||
NSString *UEFIdest = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/drivers/UEFI"];
|
||||
NSString *BIOSdest = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/drivers/BIOS"];
|
||||
|
||||
if (UEFI != nil) {
|
||||
for (int i = 0; i < [UEFI count]; i++) {
|
||||
NSString *dpath = [UEFI objectAtIndex:i];
|
||||
NSString *dname = [dpath lastPathComponent];
|
||||
if (!copyReplace(dpath, [UEFIdest stringByAppendingPathComponent:dname], attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy %@ to destination.\n", dpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BIOS != nil) {
|
||||
for (int i = 0; i < [BIOS count]; i++) {
|
||||
NSString *dpath = [BIOS objectAtIndex:i];
|
||||
NSString *dname = [dpath lastPathComponent];
|
||||
if (!copyReplace(dpath, [BIOSdest stringByAppendingPathComponent:dname], attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy %@ to destination.\n", dpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toDelete != nil) {
|
||||
for (int i = 0; i < [toDelete count]; i++) {
|
||||
NSString *dpath = [toDelete objectAtIndex:i];
|
||||
err = nil;
|
||||
if ([kfm fileExistsAtPath:dpath]) {
|
||||
post(@"- ../%@/%@\n",
|
||||
[[dpath stringByDeletingLastPathComponent] lastPathComponent],
|
||||
[dpath lastPathComponent]);
|
||||
[kfm removeItemAtPath:dpath error:&err];
|
||||
if (err != nil) {
|
||||
exitWithMessage(@"%@\n", err.description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Install tools
|
||||
NSString *cv2tools = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/tools"];
|
||||
if ([kfm fileExistsAtPath:cv2tools]) {
|
||||
post(@"\nInstalling/Updating tools:\n");
|
||||
err = nil;
|
||||
NSArray *tools = [kfm contentsOfDirectoryAtPath:cv2tools error:&err];
|
||||
if (err == nil && tools != nil) {
|
||||
for (int i = 0; i < [tools count]; i++) {
|
||||
NSString *t = [tools objectAtIndex:i];
|
||||
if ([[t pathExtension] isEqualToString:@"efi"]) {
|
||||
if (!copyReplace([cv2tools stringByAppendingPathComponent:t],
|
||||
[[targetVol stringByAppendingPathComponent:@"EFI/CLOVER/tools"]
|
||||
stringByAppendingPathComponent:t],
|
||||
attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy %@ to destination.\n", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = nil;
|
||||
|
||||
#pragma mark Install docs
|
||||
NSString *cv2docs = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/doc"];
|
||||
if ([kfm fileExistsAtPath:cv2tools]) {
|
||||
post(@"\nInstalling/Updating doc:\n");
|
||||
err = nil;
|
||||
NSArray *docs = [kfm contentsOfDirectoryAtPath:cv2docs error:&err];
|
||||
if (err == nil && docs != nil) {
|
||||
for (int i = 0; i < [docs count]; i++) {
|
||||
NSString *d = [docs objectAtIndex:i];
|
||||
if (![d hasPrefix:@"."]) {
|
||||
NSString *docpath = [cv2docs stringByAppendingPathComponent:d];
|
||||
NSDictionary *docattr = [kfm attributesOfItemAtPath:docpath error:nil];
|
||||
if (!copyReplace(docpath,
|
||||
[[targetVol stringByAppendingPathComponent:@"EFI/CLOVER/doc"]
|
||||
stringByAppendingPathComponent:d],
|
||||
docattr)) {
|
||||
|
||||
//exitWithMessage(@"Error: cannot copy %@ to destination.\n", d);
|
||||
// ... will not fail for a doc..
|
||||
post(@"Error: cannot copy %@ to destination.\n", d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = nil;
|
||||
|
||||
#pragma mark Create config.plist
|
||||
NSString *configPath = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/config.plist"];
|
||||
NSString *configSamplePath = [cloverv2 stringByAppendingPathComponent:@"EFI/CLOVER/config-sample.plist"];
|
||||
if (![kfm fileExistsAtPath:configPath]) {
|
||||
post(@"\nInstalling config.plist:\n");
|
||||
copyReplace(configSamplePath, configPath, attributes);
|
||||
}
|
||||
|
||||
#pragma mark Install theme
|
||||
// install the theme defined in config if doesn't exist
|
||||
NSDictionary *config = [NSDictionary dictionaryWithContentsOfFile:configPath];
|
||||
NSString *themesSourceDir = [cloverv2 stringByAppendingPathComponent:@"themespkg"];
|
||||
NSString *themesDestDir = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/themes"];
|
||||
|
||||
if (config != nil && ![kfm fileExistsAtPath:themesDestDir]) {
|
||||
NSString *theme = nil;
|
||||
NSDictionary *GUI = [config objectForKey:@"GUI"];
|
||||
if (GUI != nil) {
|
||||
theme = [GUI objectForKey:@"Theme"];
|
||||
}
|
||||
|
||||
// don't overwrite the theme if already exist as one from CTM can be newer
|
||||
if (theme != nil && ![kfm fileExistsAtPath:
|
||||
[themesDestDir stringByAppendingPathComponent:theme]]) {
|
||||
post(@"\nInstalling Theme \"%@\":\n", theme);
|
||||
copyReplace([themesSourceDir stringByAppendingPathComponent:theme],
|
||||
[themesDestDir stringByAppendingPathComponent:theme],
|
||||
attributes);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Stage 2 installation
|
||||
if (boot2Path != nil) {
|
||||
post(@"\nInstalling stage 2..\n");
|
||||
if (!copyReplace(boot2Path, [targetVol stringByAppendingPathComponent:@"boot"], attributes)) {
|
||||
exitWithMessage(@"Error: cannot copy bootloader to detination.\n");
|
||||
}
|
||||
|
||||
if (alt) {
|
||||
[preferences setValue:[NSNumber numberWithBool:YES] forKey:@"boot2Alt"];
|
||||
NSString *altPath = [boot2Path stringByDeletingLastPathComponent];
|
||||
NSArray *files = [kfm contentsOfDirectoryAtPath:altPath error:nil];
|
||||
if (files) {
|
||||
for (int i = 0; i < [files count]; i++) {
|
||||
NSString *f = [files objectAtIndex:i];
|
||||
if ([f hasPrefix:@"boot"]) {
|
||||
post(@"\nInstalling stage 2 \"%@ (alt)\".\n", f);
|
||||
copyReplace([altPath stringByAppendingPathComponent: f],
|
||||
[targetVol stringByAppendingPathComponent:f],
|
||||
attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Write Preferences
|
||||
NSString *prefPath = [targetVol stringByAppendingPathComponent:@"EFI/CLOVER/pref.plist"];
|
||||
if ([preferences writeToFile:prefPath atomically:YES]) {
|
||||
[kfm setAttributes:attributes ofItemAtPath:prefPath error:nil];
|
||||
}
|
||||
|
||||
saveLog();
|
||||
#pragma mark Boot sectors installation
|
||||
if (boot0Path != nil && boot1Path != nil && bootSectorsInstallSrc != nil) {
|
||||
// copy bootsectors-install
|
||||
[kfm copyItemAtPath:bootSectorsInstallSrc toPath:bootSectorsInstall error:nil];
|
||||
NSDictionary *bsiAttr = [kfm attributesOfItemAtPath:bootSectorsInstallSrc error:nil];
|
||||
[kfm setAttributes:bsiAttr ofItemAtPath:bootSectorsInstall error:nil];
|
||||
|
||||
// copy boot0
|
||||
[kfm copyItemAtPath:boot0Path toPath:[@"/tmp" stringByAppendingPathComponent:boot0] error:nil];
|
||||
// copy boot1
|
||||
[kfm copyItemAtPath:boot1Path toPath:[@"/tmp" stringByAppendingPathComponent:boot1] error:nil];
|
||||
|
||||
[kfm copyItemAtPath:boot1installPath toPath:@"/tmp/boot1-install" error:nil];
|
||||
|
||||
/*
|
||||
/tmp/bootsectors-install disk4s1 hfs FDisk_partition_scheme boot0af boot1h
|
||||
*/
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
NSPipe *pipe = [NSPipe new];
|
||||
|
||||
task.standardOutput = pipe;
|
||||
task.standardError = pipe;
|
||||
|
||||
NSFileHandle * fh = [pipe fileHandleForReading];
|
||||
|
||||
[task setEnvironment:[[NSProcessInfo new] environment]];
|
||||
[task setLaunchPath:bootSectorsInstall];
|
||||
|
||||
NSString *esp = isESP ? @"ESP" : @"OTHER";
|
||||
[task setArguments:@[ disk, filesystem, shemeMap, boot0, boot1, esp ]];
|
||||
|
||||
task.terminationHandler = ^(NSTask *theTask) {
|
||||
if (theTask.terminationStatus != 0) {
|
||||
exitWithMessage(@"Error: failed installing boot sectors.\n");
|
||||
}
|
||||
};
|
||||
[task launch];
|
||||
//[task waitUntilExit];
|
||||
NSData *data = [fh readDataToEndOfFile];
|
||||
if (data) {
|
||||
NSString *output = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
post(@"%@\n", output);
|
||||
}
|
||||
|
||||
} else {
|
||||
saveLog();
|
||||
if (isESP) {
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
[task setEnvironment:[[NSProcessInfo new] environment]];
|
||||
[task setLaunchPath:@"/usr/sbin/diskutil"];
|
||||
[task setArguments:@[ @"umount", @"force", disk ]];
|
||||
[task launch];
|
||||
}
|
||||
}
|
||||
cleanUp();
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user