mkefiboot: Make Apple boot images appear in the startup preferences
There's a small amount of additional metadata required for the Mac boot images to appear as bootable devices in the startup preferencs, so add support for generating that. Signed-off-by: Brian C. Lane <bcl@redhat.com>
This commit is contained in:
parent
1c623637d2
commit
3996d9c9e0
@ -27,27 +27,51 @@ def mkefiboot(bootdir, outfile, label):
|
|||||||
'''Make an EFI boot image with the contents of bootdir in EFI/BOOT'''
|
'''Make an EFI boot image with the contents of bootdir in EFI/BOOT'''
|
||||||
mkdosimg(None, outfile, label=label, graft={'EFI/BOOT':bootdir})
|
mkdosimg(None, outfile, label=label, graft={'EFI/BOOT':bootdir})
|
||||||
|
|
||||||
def mkmacboot(bootdir, outfile, label, icon=None):
|
def mkmacboot(bootdir, outfile, label, icon=None, product='Generic'):
|
||||||
'''Make an EFI boot image for Apple's EFI implementation'''
|
'''Make an EFI boot image for Apple's EFI implementation'''
|
||||||
graft = {'EFI/BOOT':bootdir}
|
graft = {'EFI/BOOT':bootdir}
|
||||||
if icon:
|
if icon:
|
||||||
graft['.VolumeIcon.icns'] = icon
|
graft['.VolumeIcon.icns'] = icon
|
||||||
mkhfsimg(None, outfile, label=label, graft=graft)
|
mkhfsimg(None, outfile, label=label, graft=graft)
|
||||||
macbless(outfile)
|
macmunge(outfile, product)
|
||||||
|
|
||||||
# To make an HFS+ image bootable, we need to fill in parts of the
|
# To make an HFS+ image bootable, we need to fill in parts of the
|
||||||
# HFSPlusVolumeHeader structure - specifically, finderInfo[0,1,5].
|
# HFSPlusVolumeHeader structure - specifically, finderInfo[0,1,5].
|
||||||
# For details, see Technical Note TN1150: HFS Plus Volume Format
|
# For details, see Technical Note TN1150: HFS Plus Volume Format
|
||||||
# http://developer.apple.com/library/mac/#technotes/tn/tn1150.html
|
# http://developer.apple.com/library/mac/#technotes/tn/tn1150.html
|
||||||
def macbless(imgfile):
|
#
|
||||||
|
# Additionally, we want to do some fixups to make it play nicely with
|
||||||
|
# the startup disk preferences panel.
|
||||||
|
def macmunge(imgfile, product):
|
||||||
'''"bless" the EFI bootloader inside the given Mac EFI boot image, by
|
'''"bless" the EFI bootloader inside the given Mac EFI boot image, by
|
||||||
writing its inode info into the HFS+ volume header.'''
|
writing its inode info into the HFS+ volume header.'''
|
||||||
# Get the inode number for the boot image and its parent directory
|
# Get the inode number for the boot image and its parent directory
|
||||||
with LoopDev(imgfile) as loopdev:
|
with LoopDev(imgfile) as loopdev:
|
||||||
with Mount(loopdev) as mnt:
|
with Mount(loopdev) as mnt:
|
||||||
loader = glob.glob(os.path.join(mnt,'EFI/BOOT/BOOT*.efi'))[0]
|
loader = glob.glob(os.path.join(mnt,'EFI/BOOT/BOOT*.efi'))[0]
|
||||||
|
config = glob.glob(os.path.join(mnt,'EFI/BOOT/BOOT*.conf'))[0]
|
||||||
blessnode = os.stat(loader).st_ino
|
blessnode = os.stat(loader).st_ino
|
||||||
dirnode = os.stat(os.path.dirname(loader)).st_ino
|
dirnode = os.stat(os.path.dirname(loader)).st_ino
|
||||||
|
with open(os.path.join(mnt,'mach_kernel'), 'w') as kernel:
|
||||||
|
kernel.write('Dummy kernel for booting')
|
||||||
|
sysdir = os.path.join(mnt,'System/Library/CoreServices/')
|
||||||
|
os.makedirs(sysdir)
|
||||||
|
with open(os.path.join(sysdir,'SystemVersion.plist'), 'w') as plist:
|
||||||
|
plist.write('''<?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>ProductBuildVersion</key>
|
||||||
|
<string></string>
|
||||||
|
<key>ProductName</key>
|
||||||
|
<string>Linux</string>
|
||||||
|
<key>ProductVersion</key>
|
||||||
|
<string>%s</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
''' % (product,))
|
||||||
|
os.link(loader, os.path.join(sysdir,'boot.efi'))
|
||||||
|
os.link(config, os.path.join(sysdir,'boot.conf'))
|
||||||
# format data properly (big-endian UInt32)
|
# format data properly (big-endian UInt32)
|
||||||
nodedata = struct.pack(">i", blessnode)
|
nodedata = struct.pack(">i", blessnode)
|
||||||
dirdata = struct.pack(">i", dirnode)
|
dirdata = struct.pack(">i", dirnode)
|
||||||
@ -88,6 +112,8 @@ if __name__ == '__main__':
|
|||||||
help="filesystem label to use (default: %(default)s)")
|
help="filesystem label to use (default: %(default)s)")
|
||||||
parser.add_argument("-i", "--icon", metavar="ICONFILE",
|
parser.add_argument("-i", "--icon", metavar="ICONFILE",
|
||||||
help="icon file to include (for Apple EFI image)")
|
help="icon file to include (for Apple EFI image)")
|
||||||
|
parser.add_argument("-p", "--product", metavar="PRODUCT",
|
||||||
|
help="product name to use (for Apple EFI image)")
|
||||||
parser.add_argument("bootdir", metavar="EFIBOOTDIR",
|
parser.add_argument("bootdir", metavar="EFIBOOTDIR",
|
||||||
help="input directory (will become /EFI/BOOT in the image)")
|
help="input directory (will become /EFI/BOOT in the image)")
|
||||||
parser.add_argument("outfile", metavar="OUTPUTFILE",
|
parser.add_argument("outfile", metavar="OUTPUTFILE",
|
||||||
@ -102,7 +128,7 @@ if __name__ == '__main__':
|
|||||||
print "Warning: --icon is only useful for Apple EFI images"
|
print "Warning: --icon is only useful for Apple EFI images"
|
||||||
# do the thing!
|
# do the thing!
|
||||||
if opt.imgtype == "apple":
|
if opt.imgtype == "apple":
|
||||||
mkmacboot(opt.bootdir, opt.outfile, opt.label, opt.icon)
|
mkmacboot(opt.bootdir, opt.outfile, opt.label, opt.icon, opt.product)
|
||||||
else:
|
else:
|
||||||
mkefiboot(opt.bootdir, opt.outfile, opt.label)
|
mkefiboot(opt.bootdir, opt.outfile, opt.label)
|
||||||
if opt.disk:
|
if opt.disk:
|
||||||
|
Loading…
Reference in New Issue
Block a user