Skip to content

Commit 36d658b

Browse files
committed
Enhance SmartBoot modules with new features and improvements
- Updated .gitignore to include generate_assets.py. - Refined main.py for better high-DPI support and code clarity. - Deleted unused boot_sector.py file to streamline the codebase. - Enhanced disk_formatter.py with new filesystem features and improved error handling. - Improved image_writer.py with post-write verification and progress reporting. - Updated iso_manager.py to manage ISO history and improve validation. - Enhanced usb_manager.py with richer device metadata and write-protect detection. - Refactored boot sector modules for clearer implementation strategies and improved functionality.
1 parent b245465 commit 36d658b

16 files changed

Lines changed: 3055 additions & 2027 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,4 @@ temp/
148148
output/
149149
remove_comments.py
150150
generate_icon.py
151+
generate_assets.py

core/boot_sector.py

Whitespace-only changes.

core/boot_sector/base.py

Lines changed: 183 additions & 124 deletions
Large diffs are not rendered by default.

core/boot_sector/linux.py

Lines changed: 188 additions & 158 deletions
Large diffs are not rendered by default.

core/boot_sector/macos.py

Lines changed: 76 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
"""
22
macOS Boot Sector module for SmartBoot
33
4-
Strategy:
5-
BIOS: dd MBR (best we can do without a Mac-native bootloader)
6-
UEFI: copy system EFI → syslinux efi64 → stub
7-
FreeDOS: delegates to BIOS
4+
Strategy (Rufus-parity where possible on macOS):
5+
6+
BIOS:
7+
1. dd generic MBR (446 bytes, conv=notrunc) — best we can do without
8+
a native x86 bootloader package on macOS
9+
2. Set boot flag via pdisk / diskutil (last resort)
10+
11+
UEFI:
12+
1. Copy known macOS EFI files (apfs.efi, boot.efi, gummiboot)
13+
2. Walk /usr/share/efi, /usr/lib/efi
14+
3. Minimal PE32+ stub
15+
16+
FreeDOS:
17+
Delegates to BIOS chain.
818
"""
919

1020
import os
@@ -30,25 +40,25 @@ def _sudo(cmd: List[str], **kwargs) -> subprocess.CompletedProcess:
3040

3141

3242
class MacOSBootSector(BaseBootSector):
33-
"""macOS-specific boot sector implementation."""
43+
"""macOS-specific boot sector writer."""
3444

3545
_EFI_SOURCES = [
46+
"/System/Library/CoreServices/boot.efi",
3647
"/usr/standalone/i386/apfs.efi",
3748
"/usr/standalone/i386/EfiLoginUI.efi",
38-
"/System/Library/CoreServices/boot.efi",
39-
"/usr/share/syslinux/efi64/syslinux.efi",
4049
"/usr/local/lib/syslinux/efi64/syslinux.efi",
50+
"/opt/local/share/syslinux/efi64/syslinux.efi",
51+
"/usr/local/share/refind/refind_x64.efi",
52+
"/opt/homebrew/share/refind/refind_x64.efi",
4153
]
4254

55+
4356
def check_admin_privileges(self) -> bool:
4457
try:
4558
return _sudo(["true"], timeout=5).returncode == 0
4659
except Exception:
4760
return False
4861

49-
# ------------------------------------------------------------------
50-
# Helpers
51-
# ------------------------------------------------------------------
5262

5363
def _dev_path(self, device: Dict[str, Any]) -> Optional[str]:
5464
name = device.get("name", "")
@@ -63,17 +73,25 @@ def _get_partition(self, dev: str, number: int = 1) -> Optional[str]:
6373
return candidate
6474
return None
6575

66-
def _mount_partition(self, partition: str) -> Optional[str]:
67-
"""Mount via diskutil and return the mount point."""
76+
def _wait_for_partition(self, dev: str, number: int = 1,
77+
retries: int = 6) -> Optional[str]:
78+
for _ in range(retries):
79+
p = self._get_partition(dev, number)
80+
if p:
81+
return p
82+
time.sleep(1)
83+
return None
84+
85+
def _diskutil_mount(self, partition: str) -> Optional[str]:
86+
"""Mount partition via diskutil and return mount point."""
6887
try:
6988
r = _run(["diskutil", "mount", partition], timeout=20)
7089
if r.returncode != 0:
7190
return None
72-
# Parse "Volume XXX on /dev/disk1s1 mounted"
7391
for line in r.stdout.splitlines():
7492
if "mounted" in line.lower() and " on " in line.lower():
7593
mp = line.split(" on ", 1)[-1].strip().rstrip(".")
76-
if os.path.exists(mp):
94+
if mp and os.path.exists(mp):
7795
return mp
7896
except Exception as exc:
7997
logger.warning(f"diskutil mount {partition}: {exc}")
@@ -82,26 +100,22 @@ def _mount_partition(self, partition: str) -> Optional[str]:
82100
def _resolve_mount_point(
83101
self, device: Dict[str, Any], partition: str
84102
) -> Optional[str]:
85-
"""Return an existing mount point for the partition."""
86103
mp = device.get("drive_letter", "")
87-
if mp and os.path.exists(mp):
104+
if mp and os.path.isdir(mp):
88105
return mp
89-
# Ask diskutil
106+
90107
try:
91108
r = _run(["diskutil", "info", partition], timeout=10)
92109
for line in r.stdout.splitlines():
93110
if "Mount Point:" in line:
94111
candidate = line.split(":", 1)[1].strip()
95-
if candidate and os.path.exists(candidate):
112+
if candidate and os.path.isdir(candidate):
96113
return candidate
97114
except Exception:
98115
pass
99-
# Try mounting
100-
return self._mount_partition(partition)
101116

102-
# ------------------------------------------------------------------
103-
# BIOS boot
104-
# ------------------------------------------------------------------
117+
return self._diskutil_mount(partition)
118+
105119

106120
def write_bios_boot(
107121
self,
@@ -114,38 +128,49 @@ def write_bios_boot(
114128
self._update(progress_callback, 0, "Device name not found")
115129
return False
116130

117-
self._update(progress_callback, 10,
131+
self._update(progress_callback, 8,
118132
f"Writing BIOS boot sector to {dev}…")
119133

134+
_run(["diskutil", "unmountDisk", dev], timeout=20)
135+
120136
mbr_bin = self._find_or_create_mbr()
121137
if not mbr_bin or not os.path.exists(mbr_bin):
122138
self._update(progress_callback, 0,
123139
"Error: Could not create MBR binary")
124140
return False
125141

126-
# Unmount so dd can write
127-
_run(["diskutil", "unmountDisk", dev], timeout=20)
128-
129142
try:
130143
r = _sudo(
131144
["dd", f"if={mbr_bin}", f"of={dev}",
132145
"bs=446", "count=1", "conv=notrunc"],
133-
timeout=30
146+
timeout=30,
134147
)
135148
if r.returncode == 0:
136-
self._update(progress_callback, 100,
137-
"Generic MBR written (dd)")
138-
return True
139-
self._update(progress_callback, 0,
140-
f"dd MBR failed: {r.stderr.strip()}")
149+
self._update(progress_callback, 80, "Generic MBR written (dd)")
150+
else:
151+
self._update(progress_callback, 40,
152+
f"dd MBR failed: {r.stderr.strip()}")
141153
except Exception as exc:
142-
self._update(progress_callback, 0, f"dd MBR error: {exc}")
154+
self._update(progress_callback, 40, f"dd MBR error: {exc}")
155+
156+
partition = self._wait_for_partition(dev)
157+
if partition and shutil.which("pdisk"):
158+
try:
159+
proc = subprocess.Popen(
160+
["sudo", "pdisk", dev, "-e"],
161+
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
162+
stderr=subprocess.PIPE,
163+
)
164+
proc.communicate(input=b"f 1\nw\ny\nq\n", timeout=15)
165+
self._update(progress_callback, 90,
166+
"Partition boot flag set via pdisk")
167+
except Exception:
168+
pass
169+
170+
self._update(progress_callback, 100,
171+
"BIOS boot setup complete (MBR written)")
172+
return True
143173

144-
return False
145-
146-
# ------------------------------------------------------------------
147-
# UEFI boot
148-
# ------------------------------------------------------------------
149174

150175
def write_uefi_boot(
151176
self,
@@ -163,13 +188,14 @@ def write_uefi_boot(
163188
self._update(progress_callback, 0, "Device name not found")
164189
return False
165190

166-
partition = self._get_partition(dev)
191+
partition = self._wait_for_partition(dev)
167192
if not partition:
168193
self._update(progress_callback, 0,
169194
f"Could not find first partition on {dev}")
170195
return False
171196

172-
self._update(progress_callback, 10, "Preparing UEFI boot files…")
197+
iso_type = options.get("iso_type", "generic").lower()
198+
self._update(progress_callback, 8, "Preparing UEFI boot files…")
173199

174200
mount_point = self._resolve_mount_point(device, partition)
175201
if not mount_point:
@@ -179,11 +205,9 @@ def write_uefi_boot(
179205

180206
efi_boot_dir = os.path.join(mount_point, "EFI", "BOOT")
181207
os.makedirs(efi_boot_dir, exist_ok=True)
182-
self._update(progress_callback, 20, "EFI directory structure created")
183-
208+
self._update(progress_callback, 18, "EFI directory structure created")
184209
bootx64 = os.path.join(efi_boot_dir, "BOOTX64.EFI")
185210

186-
# Layer 1: known macOS EFI files
187211
for src in self._EFI_SOURCES:
188212
if os.path.exists(src):
189213
try:
@@ -192,13 +216,13 @@ def write_uefi_boot(
192216
f"UEFI bootloader installed from {src}")
193217
return True
194218
except Exception as exc:
195-
logger.warning(f"Copy {src}: {exc}")
219+
logger.warning(f"copy {src}: {exc}")
196220

197-
# Layer 2: walk /usr/share/efi, /usr/lib/efi
198-
for efi_dir in ("/usr/share/efi", "/usr/lib/efi"):
199-
if not os.path.isdir(efi_dir):
221+
for efi_search in ("/usr/share/efi", "/usr/lib/efi",
222+
"/usr/local/share", "/opt/homebrew/share"):
223+
if not os.path.isdir(efi_search):
200224
continue
201-
for root, _, files in os.walk(efi_dir):
225+
for root, _, files in os.walk(efi_search):
202226
for fname in files:
203227
if fname.lower().endswith(".efi"):
204228
src = os.path.join(root, fname)
@@ -210,23 +234,18 @@ def write_uefi_boot(
210234
except Exception:
211235
continue
212236

213-
# Layer 3: Minimal stub
214-
self._update(progress_callback, 90,
215-
"No bootloader found — writing minimal stub…")
237+
self._update(progress_callback, 88,
238+
"No bootloader found — writing minimal UEFI stub…")
216239
stub = self._find_or_create_uefi_stub()
217240
try:
218241
shutil.copy2(stub, bootx64)
219-
self._update(progress_callback, 100,
220-
"Minimal UEFI stub installed")
242+
self._update(progress_callback, 100, "Minimal UEFI stub installed")
221243
return True
222244
except Exception as exc:
223245
self._update(progress_callback, 0,
224246
f"Stub install failed: {exc}")
225247
return False
226248

227-
# ------------------------------------------------------------------
228-
# FreeDOS boot
229-
# ------------------------------------------------------------------
230249

231250
def write_freedos_boot(
232251
self,

0 commit comments

Comments
 (0)