iVc@s^dZddkZddkZddkZddkZddkZddkZddkZddkZddk i Z ddk Z ddk Z ddkZddkZddkZddkZddkZddklZlZlZlZlZlZlZlZlZddklZlZl Z l!Z!l"Z"l#Z#l$Z$l%Z%l&Z&l'Z'ddk(l)Z)l*Z*ddk+l,Z,l-Z-l.Z.l/Z/l0Z0ddk1l2Z2l3Z3l4Z4l5Z5l6Z6l7Z7l8Z8l9Z9l:Z:ddk;l<Z<dd k=l>Z>dd k?l@Z@lAZAd ZBd ZCd e)fdYZDde3fdYZEde3fdYZFdZGdS(s* GRUB2 boot loader backend for pybootmgmt iN( t BootmgmtErrortBootmgmtArgumentErrortBootmgmtConfigReadErrortBootmgmtConfigWriteErrortBootmgmtNotSupportedErrort!BootmgmtUnsupportedOperationErrort BootmgmtUnsupportedPropertyErrort BootmgmtUnsupportedPlatformErrortBootmgmtInterfaceCodingError( t libzfs_initt libzfs_finit zpool_opent zpool_closetzpool_get_proptZPOOL_PROP_GUIDt is_gpt_diskt mnttab_opent getmntanyt mnttab_close(t BootLoadertBootLoaderInstallError(t BootConfigtDiskBootConfigt ODDBootConfigt NetBootConfigtSolarisDiskBootInstance( tget_current_arch_stringt LoggerMixint bootfs_splitt parse_booltfind_efi_system_partitiontget_zpool_default_bootfstis_zfs_encrypted_datasettwrite_temp_filetget_bootfs_list_from_libbe(tSystemFirmware(tAuthConfigParser(tMenuConfigEntrytMenuConfigParseris$C12A7328-F81F-11D2-BA4B-00A0C93EC93BtGRUB2BootLoaderc BsleZdZdZhdzd6Zeieieiei ei ei ei ei eig Zhdd6dd6Zhdd6dd6Zheiiedd edd6eiiedd edd6Zhedid d d6edid d d6Zd d gZhed6ed6Zhdd6dd6Zhdd6dd6ZdZdZdZdZdZ dZ!dZ"d{Z#dZ$dZ%e$de%Z&dZ'eiieddZ(e(e'Z)hdd6dd6d d 6d!d!6Z*d"gZ+eiiedd#d$d|fd}gZ-hd'd6d(d6Z.d)Z/d*Z0d+Z1dZ2d,Z3dZ4d-Z5d.Z6d/Z7d0Z8d1Z9hd2d6d3d6Z:dZ;d&Z<d6Z=d7Z>d8Z?d9Z@eAd:ZBeAd;ZCeAd<ZDeAd=ZEeAd>ZFeAd?ZGeAd@ZHeAdAZIeJdBZKdCZLdDZMdEZNeOdFZPdGZQd|dHZRd|dIZSd|eTdJZUd|dKZVdLZWdMZXdNZYdOZZdPZ[d|eTeTdQZ\e]dRZ^d|d|dSZ_dTZ`d|dUdVZadWZbdXZcdYZddZZed[Zfd\Zgd]Zhd^Zie]d_Zjd`ZkdaZldbZmdcZnddZoe]deZpdfZqeOdgZrdhZsdiZteTd|d|djZudkZvdlZwdmZxdnZyd|doZzdpZ{d|d|d|d|eTeTd|dqZ|drZ}dsZ~dtZduZdvZdwdxZe]dwdyZRS(sNImplementation of the BootLoader interface for the GRUB2 boot loader. itbiostuefi64tx86susr/lib/grub2/biossusr/lib/grub2/uefi64si386-pcs x86_64-efis lib/grub/t-t_tminicmdtreboottvbetefi_gopsC1024x768x32;1024x768x16;800x600x16;640x480x16;640x480x15;640x480x32ssbin/grub-installssbin/grub-mkconfigsbin/grub-mkimagesbin/grub-mkpasswd-pbkdf2is.boot_loader_update_requiredtrootis boot/grubtthemest/tsolarissshare/grub/themes/%s/theme.txttjpegtjpgtpngttgatpf2sshare/grub/unicode.pf2s unicode.pf2sboot/grub/splash.jpgs splash.jpgsboot/grub/pxegrub2sboot/grub/grub2netx64.efiscore.imgs custom.cfgsgrub.cfgs menu.confs grub2_defs.%ss auth.confisauth.cfgis boot/bios.imgs boot/uefi.imgiiit343434tF7FBFFs grub.pbkdf2cKs6|id}|djp|idjodS|itijo"tdjo|iddS|itijo|idj ot i |S|iti jot i |S|itijoTy|i ||idWn&tj o}|id|dSXt i|Std|idS(s%Probe for GRUB2 on a system. t bootconfigR*s0GRUB2 boot loader not supported on this platformtfwtypes#[PROBE ABORTED DUE TO EXCEPTION] %ssBoot class %s not supportedN(tgettNonet boot_classRtBOOT_CLASS_NETRt_debugtBOOT_CLASS_DISKt boot_fstypeR't _probe_disktBOOT_CLASS_ODDt _probe_oddt_validate_platform_and_firmwareRt _probe_netR(tclstkwargsR<tbmerr((s-../../common/bootmgmt/backend/loader/grub2.pytprobes,  cKs|id}|i}|id|tii|iddtii|iddtii|iddg}y|i||Wntj odSXt |S(s]This GRUB2 probe function searches the ODD's root, looking for the GRUB2 core modulesR<sodd_image_root=%sR(s cdboot.imgs kernel.imgR)N( R>tget_rootRBtostpathtjointGRUB_DATA_PATHSt_probe_genericRR?R'(RJRKR<R1todd_data_probe_list((s-../../common/bootmgmt/backend/loader/grub2.pyRGs"        cKs>|id}ti|}|pdS||dR't_probe_artifacts_netR?(RJRKR<RU((s-../../common/bootmgmt/backend/loader/grub2.pyRIs  cKs>|id}|i|}|pdS||dt_probe_artifacts_diskR?R'(RJRKR<RU((s-../../common/bootmgmt/backend/loader/grub2.pyREs  cCs|djotdnyJxC|D];}tii||}|id|t|iq'WWn$tj o}td|nXdS(s*Generic probe function for GRUB2. sdataroot is NonesProbing for %ss#IOError when checking for datafilesN( R?RRORPRQRBtopentclosetIOError(RJtdataroott datafilestdatafiletfpathtioerr((s-../../common/bootmgmt/backend/loader/grub2.pyRS!s c Csg}|i}|id||iftidtidg}tii|iti|i }yJti |}t i |i o$|i djo|tig7}nWntj onXy4|i|||tig7}|tig7}Wntj onX|S(sLooks for the menu.conf and the NBPs. There are no "tools" needed for NetBootConfig. The images are preassembled. s#net_image_root=%s, net_data_root=%sR(R)i(RNRBt net_data_rootR'tGRUB_NBP_PATHSRORPRQtMENU_CONF_BASENAMEt pxe_suffixtstattS_ISREGtst_modetst_sizeRtARTIFACT_BOOTLOADER_CONFIGFILEStOSErrorRStARTIFACT_BOOTLOADER_IMAGEStARTIFACT_BOOTLOADER_TOOLSR(RJR<RUR1tnet_data_probe_listt menu_conft stat_info((s-../../common/bootmgmt/backend/loader/grub2.pyRV2s,    #c Cst|dd}|o|i}n |i}|idjo |}n5|idjo |i}n|id|igStii |p|idgS|id||fg}yhtii |t i t i }ti|}ti|io$|idjo|tig7}nWn7ttfj o%}|id|t|fnXtii |id d tii |id d tii |id d g} y$|i|| |tig7}Wn+tj o}|id t|nXtidi} | d jontii |id dtii |id dtii |id dtii |id dg} nw| d joUtii |id dtii |id dtii |id dg} n|id| gSt} x| D]} y]tii d| }tii |oti!|ti"p|id|t#} PnWqtj o}|id|t#} qXqW| p|ti$g7}n|S(sBProbe for artifacts found when used with a DiskBootConfig t boot_loadertufstzfss%[PROBE FAILURE] Unknown filesystem %ssdataroot is not a directorysdataroot=%s cfgdataroot=%sisError while looking for %s: %sR(s diskboot.imgs kernel.imgR)s5Error while looking for GRUB2 kernel/loader files: %sssbin/grub-setupssbin/grub-probessbin/grub-installsbin/grub-mkimagesUnsupported firmware type: %sR3s%s not found or not executables'Error while looking for GRUB2 tools: %sN(%tgetattrR?t_get_boot_loader_data_rootRNRDtzfstopRBRORPtisdirRQR'tBOOT_GRUB_SUBDIRRbRdReRfRgRRhRitAttributeErrortstrRRRSRjRR#R>tfw_nametGRUB_PLATFORM_PREFIXEStFalsetexiststaccesstX_OKtTrueRk(RJR<t bootloaderR[t cfgdatarootRUtmenuconfRntexcpttdisk_data_probe_listtfwnametdisk_execs_probe_listt missing_toolstexecnametfull_exec_pathtoserr((s-../../common/bootmgmt/backend/loader/grub2.pyRWVs        #!                          cCsF|itijo|i|S|itijo|i|SgS(svReturns a list of artifacts for this BootLoader, given a bootconfig to use for directory information. (R@RRCRWRARV(RJR<((s-../../common/bootmgmt/backend/loader/grub2.pytprobe_artifactss cCsQ|iitijo |iS|iitijo |iiSdtiSdS(NR3( t _boot_configR@RRCt_config_dir_diskRAR`R'Rv(tself((s-../../common/bootmgmt/backend/loader/grub2.pyt config_dirs   cKsg|_d|_tt|i|d|_d|_d|_d|_ |i i t i jotii|iti|_|i}|d}t|djo |idti||fntii|iti|ti|_nw|i i t ijo`tii|i iti|i i|_tii|i iti|i i|_n|i i t i t igjoLtii|iti|_ t!|i |i|_"t#|i |_$nd|_"d|_$dS(s)Constructor for GRUB2 BootLoader tGRUB2iis'%s is %s: ONLY using %s as target valueN(%t pkg_namestnametsuperR't__init__R?t theme_os_pathttheme_grub_pathttheme_mods_setttheme_fonts_setRR@RRCRORPRQRRbt_menu_conf_patht_get_target_listtlenRBRtPROP_BOOT_TARGStGRUB_BOOT_SUBDIRStAUTH_CFG_BASENAMEt _authcfg_pathRAR`RctAUTH_CONF_BASENAMEt_authconf_pathtGRUB2MenuOrganizert _menu_orgR$t _auth_conf(RRKt target_listttarget((s-../../common/bootmgmt/backend/loader/grub2.pyRsD            cCs(d|_d|_d|_d|_dS(sEUninitialized all theme attributes (resets to default theme) N(R?RRRR(R((s-../../common/bootmgmt/backend/loader/grub2.pyt_clear_theme_states   cCstt|i|iitijoti|i ti  c Cs\|i}|d}|o"tii|ti}t}nt}|i}|i ||i d||i i o|i ii|i i djo\t|i _|i iio/|i||i ii}||i i d(Rtdef_dictttargnamet vidbackendt video_insmod((s-../../common/bootmgmt/backend/loader/grub2.pyt_generate_grub2_load_video_funcs c Cs1t|ito&t|idddjo t}nt}ti|}d}|o|i||}n|i dod}d}n d}d}d ||||f} |i |ti || d |} d |od ndti f} |i |ti |d | | ft} |o | | gSdS(s\Generates the stub config files for the platform-specific config directory. RDRRqtuefit multiboot2tmodule2t multiboottmodules0set target=%s set multiboot=%s set module=%s %s Rs%s/boot/grub/%ss/@s!if [ -s %s ]; then source %s fi N( RRRRrRR{R'R%R*t startswithR#tGRUB_CFG_BASENAMEtCUSTOM_CFG_BASENAME( RRRR&RR'R)R.R/t grubscriptt stub_grub_cfgt custom_nametstub_custom_cfg((s-../../common/bootmgmt/backend/loader/grub2.pyt_generate_stub_filess8            cCsd}t}|iitijo`|iio$|iiti d<|i dn|ii pdti d<|i dqnzyh|o|i |||n=|i ||}|ti d<|i d|i|||iWn@tj o4yti|iWntj onXnXWdx|D]}ti |=q>W|oF|o?t|dt o+yti|Wqtj oqXnXdS(s%Create and populate the grub.cfg filetBOOTMGMT_ZPOOL_LISTR{tBOOTMGMT_VALIDATE_BOOTFStBOOTMGMT_GRUB2_DEFAULTSNt preserve_defs(R?tlistRR@RRCt rpool_onlytzfsrpROtenvirontappendtvalidate_bootfst_internal_mkconfigt_generate_grub_defst_invoke_grub_mkconfigRYRtremoveRRiRrR{(RRRt defs_dictR"tgrub_defs_patht reset_envtenv_var((s-../../common/bootmgmt/backend/loader/grub2.pyt_generate_grub_cfg_filesB       Rc Csd}|o|ii}|tijoAti|}tii|ii |}tii||}qdti dti}tii||d}n&tii|i ti} | d}y |i |t |d} Wn=tj o} td|| ntj o nX|i|||| |oa|i} | od| d} nd} | |id7} ti|d | d d tifgS|i||i|| d S( sWrites the grub.cfg file to the appropriate location. If defs_dict is not None, internal grub-mkconfig is used. RR3is.newRs4Error during grub.cfg generation: Couldn't create %ss%(s)s/R1N(RR@RRAR'R1RORPRQtnet_tftproot_subdirRvRRRRZRRJRtlstripRR?RR7t_move_temp_to_grub_cfg(RRRRFt filesuffixt dest_pathR@t base_grub_cfgR!tfinal_filenameR"R RR((s-../../common/bootmgmt/backend/loader/grub2.pyR3sL         cCsd}t|itoMt|idd}|djo ti}q|djo ti}qnNt|ito ti }n.t|it o t i }n|i d|S(s[Returns the token to use when constructing tuples returned from install(). RDRqRps,Unknown BootConfig type -- not using a tokenN( R?RRRRrtTOKEN_ZFS_RPOOL_TOP_DATASETRtTOKEN_SYSTEMROOTRtTOKEN_ODD_ROOTRtTOKEN_TFTP_ROOTRB(RRtfstype((s-../../common/bootmgmt/backend/loader/grub2.pyRhs      c Csy$ti|||id|Wnmtj oa}yti|Wn+tj o}|id||fnXtd||f|nXyBti|t i ti |t i ditidiWn(tj o}td||nXdS(s6Moves the temporary grub.cfg.new to grub.cfg. sgrub.cfg moved into place as %ss#Error while trying to remove %s: %ssCouldn't move %s to %sR1sCouldn't set mode/perms on %sN(tshutiltmoveRBRZRORERiRRR'RRRRRRRR(RtsrcRR R((s-../../common/bootmgmt/backend/loader/grub2.pyRM|s$ cCsytiidti|tidtii|iti|g}z"|i|d|d||Wd|i XdS(sEInvokes grub-mkconfig and directs its output to the outfile. R3s --prefix=%ss-Generating %s boot loader configuration filess%s grub.cfg generationN( RORPRQR'Rzt GRUB_MKCONFIGRRt _execute_cmdRY(RRR"t grub_mkconfig((s-../../common/bootmgmt/backend/loader/grub2.pyRDs    c Cstiidti|tig}y|i|ddtd|d}|iti }|djo|i dd S|i d}|djo|i dd S|||!}|SWn|i dnXd S( s,Invokes grub-mkpasswd-pbkdf2 script R3s#Generating grub pbkdf2 for passwordt return_stdouttinputiis;Error generating pbkdf2 password using grub-mkpasswd-pbkdf2s N( RORPRQR'RztGRUB_MKPASSWORDR[RRRRBR?trfind(RRRtgrub_mkpasswd_pbkdf2tpwt start_indext end_index((s-../../common/bootmgmt/backend/loader/grub2.pyRs&          c Cs|otii|ti}n |i}tii|ti|}|i|yt|d}Wn$t j o}t d|nXx7|i |i D] \}}|d||fIJqW|i |S(sEGenerate the GRUB2 defaults file either in the specified path or in the system location. Returns the path to the defaults file. This is suitable only for DiskBootConfig. May raise BootmgmtConfigWriteError if there was a problem creating the defaults file (or its parent directory). RsError writing GRUB2 defaultss%s='%s'(RORPRQR'RvRtGRUB_DEFS_PATH_FMTRRXRZRt_generate_grub_defs_dictRRY( RRRtdirpatht defs_patht defs_fileR_RR((s-../../common/bootmgmt/backend/loader/grub2.pyRCs      cCsh}|iti}|d jo ti}nt|djoQ|ddjo|d}ntii |i tii |}||dt GFX_MODELISTRRRRR?RtupdateR|tPROP_CONSOLE_SERIALtPROP_SERIAL_PARAMSt_grub2_serial_cmdRB( RRRvt video_backendtconstintermtouttermt serial_paramst serial_cmd((s-../../common/bootmgmt/backend/loader/grub2.pyt_generate_grub_defs_dict_conss:   c Cs>h}|i|i||iti}|djo d}n|d jo ti}n||d<|iti}|ot |t jp t |od|d,,, |

,,). | is currently defined to be a | number (valid values depend on the platform, | but '0' is ttya (com1) and '1' is ttyb (com2)). | Serial console parameters (=data bits, |

=parity ('N','E','O'),=stop bits ('0','1'), | =flow control ('H','S',None) for hardware, | software, or none). The default is: | ('0',None,None,None,None,None). tnotNteventEtoddtORs*Serial parameters are None: Using defaultss --unit 0sInvalid serial parameters: %siis --port %ss --unit %sis --speed %sis --word %sis --parity %sis --stop %sN( R?RBRttupleRxRtintthexR>(Rtparamst parity_dicttcmd((s-../../common/bootmgmt/backend/loader/grub2.pyRks*   $"$$$"$c sSgtiitiii|tiitii|}dtidd|}ii t i jo'ii djod|}ndi d||f|o/tii|ti}tii|i|ttfd}tidty0i dftid |WnDtitfj o/}i d |tidtnXtii|}__||fSii t i jodStiiiti}i|tii|tii|}tiiotidty*i dftiWqFtitfj o/}i d |tidtqFXn9tii|pi d |dSi d |d ||fS(seCopy all files associated with the theme whose theme file is specified into the proper location. Returns a 3-tuple of (1) tuples (if basepath is set) (or None if not), and (2) the *GRUB path* to the theme_file (the GRUB path will be used directly in the grub.cfg file) and (3) The OS path to the theme_file. R3Rqs/@Rs3THEME: src=%s, theme=%s, theme_bn=%s, grub_path=%s c spxi|D]a}tii||}tii|pqn|iddd}tiidti|}titii|d di d|dddf}i d t |i ||id d}t|djon|d}tii|} | oi| qh|tijo&tii|} i| qhqqWgS( s%dirnm is the source theme's directoryR3Ris%(s)sR1tbinisTHEME: New tuple: %st.N(RORPRQtisfileRR'tBOOT_GRUB_THEME_SUBDIRRRR?RRBRxR@trsplitRtEXTN_TO_MODULER>taddtFONT_EXTN_LIST( tdirnmtlistingtentryt source_filet destcomponentt root_rel_pathtnewtupt extensiontextntmodnametfontpath(t theme_namet source_dirtgrub_path_prefixRtdest_theme_dirRRR(s-../../common/bootmgmt/backend/loader/grub2.pytcollect_tupless8       t ignore_errorssTHEME: Copying %s -> %stignoresError during theme copy: %ss+Could not fall back to existing theme in %ss$Falling back to existing theme in %sN(NNN(NNN(RORPtdirnameRQRsRpR'RRR@RRCRDRBt _make_dirtreeRRWtrmtreeRtcopytreetErrorRiRRR?Rt THEME_SUBDIRR|( RRt theme_filettheme_file_basenamet grub_pathtdest_dirRtcopyerrtos_path((RRRRRRRRs-../../common/bootmgmt/backend/loader/grub2.pyt_assemble_grub_theme_filessv       $$             c Cs=|i|ti}|iti}d}|tijot}ti |i jo4|iti }|oti |}qd}nti }t }y0|o%|i||\}|_|_nWq ttfj o'}|id||pqq Xn|o|o|i|n|S|o|SdS(s|Copy other needed GRUB2 files into the proper location. Return the appropriate tuples (if basepath is set). s*Exception while assembling theme files: %sN(t_assemble_grub_files_genericR't GRUB_OTHERSRRRR?RR{RRtTHEME_TEMPLATEtTHEME_DEFAULT_PATHRRRRRZRiRBR( RRRtconstypet theme_tuplest default_themet themenameRR((s-../../common/bootmgmt/backend/loader/grub2.pyR*s6    ) c Csg}x|D]\}}}tii|i|}|otii|ti}n |i}tii||}|id||f|i||p ti }nyt i ||Wn7t t i fj o"} |id|| fq nX|pzyKti||dti|ti|diti|diWqtj o} td|| qXq |i} | od| d} nd } | tid |7} |iti|d | |d|d|dfq W|o|Sd S( sUsing the list of 3-tuples passed in file_tuples, copy those files to proper destination with the proper modes. This is suitable for DiskBootConfig and ODDBootConfig only. ssrc = %s, dest = %ssCould not copy %s for GRUB2: %siiisCouldn't set mode/perms on %ss%(s)s/R3N(RORPRQRsR'RvRRBRtGRUB_OTHERS_PERM_DEFAULTSRWtcopyRZRRRRRRRRRRiRRR@RRR?( RRt file_tuplesRRYRtpermstdestdirtfulldestRRRR((s-../../common/bootmgmt/backend/loader/grub2.pyRUsF     #cCs|idt||}|i||x1|iiD]#}|i|||idq9Wd|jo|idndS(sjA stripped-down barebones implementation of a GRUB2 menu generator. First, a set of header script code is emitted (its contents depends on the values in the defs_dict (a dict representation of the $prefix/etc/default/grub file), followed by the menuentries that correspond to the boot configuration's boot_instances list. s# GRUB2 configuration file s t NO_CUSTOM_CFGsH if [ -f /boot/grub/custom.cfg ]; then source /boot/grub/custom.cfg fi N(RtGRUB2MenuEntryEmittert_internal_mkconfig_headerRRtwrite_menuentry(RRRFR"temittertbootinst((s-../../common/bootmgmt/backend/loader/grub2.pyRBs   cCsW|id}|o=t|ttfo|St|to|idSngS(sqReturns the list of lines in the script preamble stored in the definitions dictionary passed in. t__SCRIPT_PREAMBLEs (R>RR<RRtsplit(RFtpreamble((s-../../common/bootmgmt/backend/loader/grub2.pyt_grub_cfg_preamblescCsg}|i|i||id|id}|id}g}|o|i}d|jo|idt}nt}x=|D]5} |i| ||} |i| || g7}qW|o0|id||} |i| |d7}q|id|n|ooxW|iD]I} | |joq*n|i| ||t} |i| || 7}q*W|id|n|ddjo|idn|id } |id } | o/|id | |id |id n|id| |id|id} | o"|id| |idnx(|D] }|i ||i dq_WdS(sKOutput the grub.cfg header for this target based on the defs_dict. sload_video_$targetRRRsterminal_output %ssterminal_input %siRRRs+if sleep --verbose --interruptible %s; thens set timeout=0tfisset timeout=%sRsset default="%s"s N( RRR@R>RRERR{t_mkcfg_consdevR(RRFR"Rtoutdevtindevt initted_devstoutdevst do_gfxtermtdevt conslinesRRRtline((s-../../common/bootmgmt/backend/loader/grub2.pyRsd              cCsKg}|djo|o|id}|id}|id}|id} |id|o|id|ng} |id} | o|io6x3|iD]$} |id | | i| qWn|ioCx@|iD]1} |id | |id |id qWn|id |id|id| |id||idd}t}n d}t}|i|d|i|d||o|i|d|n| o|i|d| n|o|idd}t|djoGti i|d}|o&|| jo|i|d|qfn|i|d|n|i ddi }|o*|i|d|i|d|n|i|d |o|id qGnS|djoE|id}|o|i|qG|i d|idn|S(sGReturn a list of lines that init the specified terminal device RR~RjRkRlsinsmod gfxtermsset gfxmode='%s'Rms insmod %ssif ! loadfont %s ; thens set theme_dep_load_failed=1Rs)if [ x$theme_dep_load_failed = x ] ; thens loadfont /boot/grub/unicode.pf2s set theme=%ss terminal_output %stelses Rs)if loadfont /boot/grub/unicode.pf2 ; thens foreground_color %ss background_color %sRis insmod %ss background_image -m stretch %sRRs,No serial command specified -- using default( R>R@RRRR{RRR'RRtstripRB(RRtalldevsRFRRtmodestbackimgRyR{t loaded_modst themefileRRtindenttneed_fiRtimgmodtalldevs_minus_gfxtermt serialcmd((s-../../common/bootmgmt/backend/loader/grub2.pyRsz                c Cs|ptdn|i}g}|o+|i|}|o|i|q[nt}x|D]}|i||}|i|}|p7|i|||} | o|i| nt}n|i ||d|} | o|i| n|o|i|qhqhW|S(sTo generate the grub.cfg file for an ODDBootConfig, we create the menu by hand (we do NOT use the grub-mkconfig program). s,basepath must be specified for ODDBootConfigR&( RRRRR{t_create_grub2_imageRfRRR7( RRRRt of_tuplestgenerated_grub_cfgRt loader_tuplesRFt gcfg_tuplest stub_list((s-../../common/bootmgmt/backend/loader/grub2.pyRQs4     cCs|ptdn|i}g}|i|}|o|i|ndti}h}x?|D]7}|i|||<||i|||d7}qjW|d7}t}x|D]}|i ||} | o|i| n|p||} t | d<|| d<|i ||| |i i } | oxg} xX| D]P} t| }|titijoti|tiyti)|Wnt*j onXt d#|nXt+}nt,}|d$}|d%}|d&}yti-|}Wnt*j o d}nX|djo t+}qt,}y't.i/||d't,o t+}nWqt*j oqXnt0|d(| i|t+}zYy|ob|d)di | IJ|i'| d*t+d+t+\}}|d,|I|d-|I|d.IJn|i'| d/d0Wnt1j o}t,}|i2ti3joti i |ti4}yt5|d1i6Wn(t$j o}t d2||nXt7i8d3d4t7i9t7i7t7i:d5|t7i;q/t d6|nXWd|djoCz yti-|} Wnt*j o d} nX|os| ol| i<d4jo\|oUy%|i|d7t=i>||Wqt$t*t1fj o|id8qXn|od9|g}!|i'|!n|o1| djp| i<d4jot d:|nWd|o+yti)|Wq~t*j oq~XnXnX| oti?| ndS(;s/Write the GRUB2 boot loader to disk. We support 4 scenarios: (1) BIOS systems, installation onto a DOS-partitioned disk with a Solaris partition -- boot loader is embedded in the Solaris boot slice (usually slice 8, but really it's any slice that includes cylinder 0). The devname passed in can be directly passed to grub-install, as grub-setup has been modified to write the loader to the appropriate place in the Solaris partition; (2) BIOS systems, installation onto a GPT-partitioned disk. A BIOS Boot Partition (BBP) is required. The devname passed in refers to the partition that includes the ZFS, not the BBP, so we need to figure out if we're on a GPT-partitioned disk, and pass the whole-disk node (p0) to grub-install so *IT* can locate the BBP and install GRUB2 there; (3) UEFI systems, installation onto a DOS-partitioned disk. The device node refers to a VTOC slice, so we need to get the device node for the EFI System Partition, mount it (if it's not already mounted), and invoke grub-install, telling it to install the EFI boot application under EFI/ORACLE/ on the ESP; (4) UEFI systems, installation onto a GPT-partitioned disk. Similar to (3). s/Ignoring _write_loader() for non-DiskBootConfigNiitsiiitBOOTMGMT_TESTINGs%TESTING is set: NOT installing loadersDevice node is not a slice: R3s --no-floppys--grub-directory=%ss--pkglibdir=%sRs--password_file=%st ask_passwds3Failed to append ask_passwd to grub install commands --modules=%sRs--no-check-versionings--debugR(s --force-mbrtp0R)s@Could not determine the EFI System Partition (ESP) for device %st mnt_specialt mnt_mountptdirs/system/volatilesAError while trying to create a temporary dir for mounting the ESPs/usr/lib/fs/pcfs/mounts9Error while trying to mount the EFI System Partition (%s)s /EFI/ORACLEs/efi/boot/bootx64.efis /grubx64.efitshallows is not supporteds5Output from boot loader installation command "%s" is:R]t return_stderrs : %ss : %sssInstalling boot loadersBoot loader installationRsiUnable to install GRUB2 boot loader and unable to create required deferred boot loader activation file %sspybootmgmt-GRUB2isGRUB2 could not be installed at this time. The GRUB2 utilities on the root filesystem are older than (and incompatible with) the GRUB2 modules in %s. The new version of GRUB2 will be installed automatically when booting the Solaris instance in which the new GRUB2 modules are located.sGRUB2 installation faileds /efi/boot/s<Failed to copy boot app to default boot location -- ignorings /sbin/umounts8Error while creating the UEFI boot loader (size=0) on %s(@RRRRBRtisdigitROtgetenvR?RRRyRPRQRR'RRRRRzt GRUB_INSTALLtPRELOADED_MODULESRRR!R@tdictR>Rt PLATOPT_MBRR`RRRRRRZttempfiletmkdtempR[RtrmdirRiRR{RdtfilecmptcmpRRtretcodetEXIT_CODE_INCOMPATIBLEtDEFERRED_ACTIVATION_FILENAMERXRYRRRt LOG_NOTICERRgRWtcopyfileRE("Rtdevnamet data_rootRRRRt prefixdirt fulldatadirt grub_inst_cmdtpreloadsttemp_file_namet base_devnamet wholedisktis_gpttinstdevtesp_devt esp_mountptt esp_tempdirt mntentdictR_t mount_cmdt need_unmounttdefault_bootapptoracle_bootapptdefault_statinfotcopy_efi_boot_to_defaultt cmd_succeededtcmdouttcmderrtbmwerrt defer_filetstatinfot umount_cmd((s-../../common/bootmgmt/backend/loader/grub2.pyt _write_loaders> $$         #                            c Cs8t|itogSt|itpgStii|iti |}g}ti dti |}|i tii||xti |D]}|idp-|idp|idp |idpqn|idd|jo|id|qntii||}tii|||} yti|| Wnttifj ow} |id || | fx9|D]1} yti| d Wqtj oqXqWtd || f| qX|iti| dd tid tiid||dddfqW|S(sCopies GRUB2 modules (and config files) to a directory under basepath. Returns a list of tuples, each of which describes one of the files copied. This is suitable for DiskBootConfig and ODDBootConfig only. R3s.mods.lsttefiemus.imgRisSkipping copying file %ss Error while copying %s -> %s: %sis'Error while copying GRUB2 file %s to %ss%(s)sR1iN(RRRRRORPRQRsR'RRRvRRtlistdirtendswithR0RRBRWRRiRRERR@RRR?RT( RRRtexclusion_listtmodpathRt boot_subdirRtsrcpathtdestpathRttup((s-../../common/bootmgmt/backend/loader/grub2.pyt_copy_grub2_modssP      cCs3t|ito|i|}nd}d}t|itoJ|djo|i||}q|djo|i||}qnXt|itoD|djo|i|}q|djo|i |}qn|ot i |n|dj o|St d|ii i|fdS(sConstruct the bootable grub2 image for the specified target. The boot image is BootConfig-specific (BootLoaders associated with ODDBootConfig instances get BIOS-targeted El Torito images and UEFI64- targeted FAT filesystem images with embedded UEFI64-targeted boot applications (suitable for direct inclusion in an ODD image); NetBootConfig boot loaders get BIOS PXE images and UEFI64 net boot application images). R(R)s%s and target=%s not supportedN(RRRt_create_microconfigR?t_create_bios_odd_imaget_create_uefi64_odd_imageRt_create_bios_pxe_imaget_create_uefi64_net_imageRWRRRR(RRRt microconfigttuples((s-../../common/bootmgmt/backend/loader/grub2.pyR s(      cCstidtid}tii||ti}|i|tii|tid}|i|ddddddg}|i ti d|i d|||ytii|i ti d}tii|d }t|d } x*||gD]} tit| | qW| iWn.ttfj o} td || nXti|dddddfti|dd tid tiid|tidddfg} |id||} | o| i | n| S(sCreate an El Torito image by invoking grub-mkimage with the proper parameters, then prepending the result with cdboot.img. R3R(tbiosdisktiso9660t part_msdost part_sunpctpart_gpttufs1s cdboot.imgtwbs$Could not finish construction of %ss%(s)sR1iN(R'RvRRORPRQtCORE_IMG_BASENAMERtEL_TORITO_IMAGENAMESRR)t_grub2_mkimage_genericRsRRRXRWt copyfileobjRYRiRZRRtOUTPUT_TYPE_BIOS_ELTORITOR?RRRTR\(RRRbRXt imagenametwholeimagenametmodlistRWt cdboot_imgtwholeimgtfnameRRt mod_tuples((s-../../common/bootmgmt/backend/loader/grub2.pyR^; sF           c CsOtii|iti|}tiidti|ti}|od|i||}|i ddddddg|d|d |d ti |d |d g |}nPd}|d|d |d ti |d tiidti ti |g|}|i|d|d||o+yti|WqKtj oqKXndS(sCreate a GRUB2 boot image for the specified target, named imagename, with modlist modules embedded and preloaded. If microconfig is not None, it must be the path to a directory containing a boot/grub/grub.cfg file. R3tmemdiskttartsearchtgziotregexpt configfiles-os-ds-Os-ms--prefix=(memdisk)/boot/grubs --prefix=%ssGenerating %s boot loader images%s boot image generationN(RORPRQRsR'RRRzt GRUB_MKIMAGEt_make_memdisk_imageRtMKIMAGE_FORMATSR?RvRR[RERi( RRRpRrRbRWtbase_cmdt memdisk_pathtimg_cmd((s-../../common/bootmgmt/backend/loader/grub2.pyRmm s4       c CsFd }d }zytidddt}ti}ti||id|ddddg}|i|d |d |||i |i SWnct j oW}|o8|i yti |i Wqt j oqXnt d |nXWd |o;y!ti||id|WqAt j oqAXnXd S( sCreate a "tarfs" (tar file) with the microconfig specified. The microconfig specified is the parent directory -- there must be a boot/grub/grub.cfg under that directory. R#s/system/volatiletdeletes cwd => %ss/bin/tartcfR+tbootsGenerating %s memdisk images%s memdisk image creations-Error during GRUB2 memdisk image constructionN(R?R,tNamedTemporaryFileR{ROtgetcwdtchdirRBR[RYRRiRER(RRbRt memdisk_imgtorig_dirttar_cmdR((s-../../common/bootmgmt/backend/loader/grub2.pyR~ s:        c Cs=di|} |id| y|o|i|n|p| o ti} n|} |p|o ti} n| } |o ti}nti|d|d| d| } |o;|d} | ii| | ii| | iind}d}g}| tijo|i| i i n| tijo|i| i i nx@|D]8}t i |t i }t i |t i|tiBqaWx| idjoy+| tijo|| i i7}nWn<tj o0}|itijo|id|qnXy+| tijo|| i i7}nWn<tj o0}|itijo|id|qnXtid |o|id qqW| i}y+| tijo|| i i7}nWn%tj o}|id |nXy+| tijo|| i i7}nWn%tj o}|id |nX|d joU|id |||f|p d}ntd||d ||fd|n|o|idn|p|o ||fSdSWn>tj o2}|id| |ftd| |nXdS(sSpawn a command. Rs Invoking %ststdintstdouttstderrs Rs(Error while reading from stderr pipe: %sg?Rs#Error reading final stderr data: %sis5.failed (exit code %d). stderr was: %s stdout was: %sscommand executions:Error during %s: %s returned error code %d. stderr was: %sR1s.completed successfully.sError while invoking %s: %ssError invoking %sN(RQRBt subprocesstPIPEtPopenRRRYR@RtfilenoRtfcntltF_GETFLtF_SETFLROt O_NONBLOCKtpollR?treadRZterrnot EWOULDBLOCKttimetsleept returncodeRRi(RRRt whatisthist stdout_filet stdin_fileR]R%R^tfullcmdt stdout_valt stderr_valtproct user_inputt stdout_outputt stderr_outputt filedescstfdesctfcinfoR_R1R((s-../../common/bootmgmt/backend/loader/grub2.pyR[ s     !             c1sgfd}yEtidddt}|i|iifdWn$tj o}td|nXddd d d g}|it i d i d ||t i i|t id yiWn+tj o}|td|nXyt i i}|t ijo t i}ntd } | i|d| id| iifdWn1ttfj o} |td| nXddg} t| dd; ss5Error during 64-bit UEFI El Torito image constructionReRfRgRhRiR)Ritcs tiS((RORE((Rp(s-../../common/bootmgmt/backend/loader/grub2.pyR^ ss /sbin/lofiadms-as-dR]ics iS((R[((Rt lofiadm_d_cmd(s-../../common/bootmgmt/backend/loader/grub2.pyRj ss/lofi/s/rlofi/slofi association: %s => %ssCreating pcfs on image size %dKis/usr/lib/fs/pcfs/mkfss-osnofdisk,size=%dRs /dev/zerotrcs tiS((ROR.((t mount_tempdir(s-../../common/bootmgmt/backend/loader/grub2.pyR ss/usr/lib/fs/pcfs/mounts /sbin/umountcs iS((R[((RRQ(s-../../common/bootmgmt/backend/loader/grub2.pyR ssEFI/BOOTs BOOTx64.EFIs&Unmounting the uefi64 image failed: %ss3Removing temp mount dir for uefi64 image failed: %ss#Removing lofi associated failed: %ss%Removing temp uefi64 image failed: %sN((R,RR{RYRR@RiRRR'R)RmRORPRQRlRRtgetsizetUEFI_FS_MIN_SIZERXtseekRRZR<R[RRRRBR-RRWR5R.RERtOUTPUT_TYPE_UEFI_ELTORITOR?R\(RRRbRttmpfRRrRLt imagesizet imagefiletun_errt lofiadm_cmdtlofidevt raw_lofidevtmkfs_cmdREt image_destdirRRRv((RpRRRRQRRs-../../common/bootmgmt/backend/loader/grub2.pyR_" s                   cCs tii|iiti|S(sCopies the NBP program for the specified target to the specified path. Raises BootmgmtConfigWriteError if the copy failed. (RORPRQRtnet_osimage_rootR'Ra(RR((s-../../common/bootmgmt/backend/loader/grub2.pyt _nbp_path scCs(ti|iddddddfgS(sYCreate a GRUB2 image bootable via the PXE on systems with BIOS firmware. R(N(RtOUTPUT_TYPE_BIOS_NBPRR?(RR((s-../../common/bootmgmt/backend/loader/grub2.pyR` s cCs(ti|iddddddfgS(spCreate a GRUB2 UEFI boot application image bootable via the native UEFI network boot mechanism. R)N(RtOUTPUT_TYPE_UEFI64_NBPRR?(RR((s-../../common/bootmgmt/backend/loader/grub2.pyRa s c Csg}t|itot}|id |}|oK|i||idtii dt i t i ||idn|i ddi |ntd|iii|pd Sd }ytidd}tii |d }|i|d ttii |t id }x(|D] }|i||idq0W|i|SWn?tj o3} |oti|tntd | nXd S(sCreate a small configuration file whose purpose is one: (a) to locate the REAL root device (since the microconfig file will be loaded from a memdisk baked inside the GRUB2 image), or (b) to source the REAL configuration file (i.e. when booting from the network, the microconfig contains the GRUB2 script that searches the tftp hierarchy, in accordance with the Solaris-defined search order for the GRUB2 configuration file.) sset prefix=($root)%sR3ssource $prefix/grub.cfgsMicroconfig: %ss s/Microconfig creation not supported for class %sR#s/system/volatiles boot/grubiRs-Error while trying to write GRUB2 microconfigN(RRRRtsearch_cmd_genericR?R@RORPRQR'RvRRBRRRR,R-RRXR1RRYRZRWRRR( RRRRt root_searchttmpdirt tmpfiledirtcfgfileRR ((s-../../common/bootmgmt/backend/loader/grub2.pyR] sB      icCs |itii||dS(sCreate directories for dirname(basepath). May raise BootmgmtConfigWriteError if there was a problem creating the directories. N(RRORPR(RRtmode((s-../../common/bootmgmt/backend/loader/grub2.pyR! sc Csztid}zVyti||Wn;tj o/}|itijotd|qdnXWdti|XdS(sCreate directories for path. May raise BootmgmtConfigWriteError if there was a problem creating the directories. isCould not create directoryN(ROtumasktmakedirsRiRtEEXISTR(RPRt old_umaskR((s-../../common/bootmgmt/backend/loader/grub2.pyR) s(sbiossuefi64(srootsrootiN(sboot/grub/splash.jpgs splash.jpgNii@(Rt __module__t__doc__tWEIGHTtSUPPORTED_PLATFORMSRRRRRRRqRttPROP_IDENT_FILERtSUPPORTED_PROPSRzRRORPRQRRRR%tPRELOADED_MODULES_COMMONR)RRRR(RZR}R_R2R3RRvRRt THEME_DEFAULTRRRRR?RRaRkR2R1RRbRReRRRRRlRRoRRrRuRt classmethodRMRGRIRERSRVRWRtpropertyRRRRRRRRRR{RRRRRRRR#t staticmethodR*R7RJRRRMRDRRCR|RRfRsRRRRRBRRRRRRRRR\RR^RmR~R[R_RR`RaR]RR(((s-../../common/bootmgmt/backend/loader/grub2.pyR'Ks                        $r  0      4 R >/+ 8 4      0 3  0 + 3  L X , O" 7 & 3 ' + a    ; RcBseZdZdZedZedZdZdZdZ dZ ddZ de d Zed Zd Zd Zd ZdZedZedZRS(s%GRUB2MenuOrganizer includes shared code between the GRUB2 pybootmgmt backend and the GRUB2 menu generator program in $PREFIX/etc/grub.d. Methods are provided to get an ordered list of boot instances from the system (via the autogen backend (which gets the list of BEs and generates a boot instance for each BE) if none exist in the menu.conf) and the rest from the menu.conf, which has sections for each customized boot instance (and, therefore, menu entry)) and to synch a list of boot instances with the menu.conf. cCs2tt|id|_||_||_dS(s+Constructor for GRUB2MenuOrganizer N(RRRR?t_mcpRR(Rt boot_configtmenu_conf_path((s-../../common/bootmgmt/backend/loader/grub2.pyRF s  cCs|io |iiStS(sYPseudoproperty returns True of the underlying MenuConfigParser is dirty. (RRR{(R((s-../../common/bootmgmt/backend/loader/grub2.pyRN s  cCs8|iio |iiS|iio |iiSdSdS(s=Accessor for the path to the last menu.conf written. N(Rtlast_written_pathtfilenameR?(R((s-../../common/bootmgmt/backend/loader/grub2.pytmenu_conf_sourceW s     cCst|it|_dS(s9Start over with a new (empty) menu configuration N(R&RRR(R((s-../../common/bootmgmt/backend/loader/grub2.pyRb scCs8|ii}t|}|id|iti|S(s]Returns a dictionary of properties from the global section of the menu.conf. sSerial properties: %s(Rtglobal_optionsR*RBR>RR(Rt global_propstblprops((s-../../common/bootmgmt/backend/loader/grub2.pyRg s    cCs|i}|oH|ii}|o.|i||}|o|iiqWqn|iitijokddk l }|i |idg}x@|D]4}|i i }|i|}|ii||qWn|S(sLoad the menu.conf file and processes the sections, generating BootInstance objects and returning the list to the caller. i(tBootInstanceAutogenFactoryR4(t_build_custom_inst_listRt get_ordert_rearrange_inst_listt clear_orderRR@RRCtbootmgmt.backend.autogenRtautogenRRt_boot_instance_to_propdictt add_entry(RRtexplicit_ordert do_updateRtinstt classnametpropdict((s-../../common/bootmgmt/backend/loader/grub2.pyRs s"    c sx|iD]\}}|tijo|tijogy=g}x!|D]}|it|qIWdi|}Wqtj o|i dq qXnt||i i |t_menu_conf_entryt_write_menuentry_tcmp_fncs |ijS((tsection_string(R(t order_list(s-../../common/bootmgmt/backend/loader/grub2.pyR sN('RR'RRRR@RxRQt TypeErrorRBRRRR@RRCRAR"R?RRRrRt cred_listRRRRR<t_synch_boot_instance_to_entryRRRRRRRt set_ordertdelete_entries(Rtbi_listtbl_propsRRtstrlisttitemtvalid_bootfsesRt inst_bootfsR t custom_entryRRR((Rs-../../common/bootmgmt/backend/loader/grub2.pyR s`             cCs*|o ||_nt|i|_dS(s+Loads the menu configuration file. N(RR&R(RR((s-../../common/bootmgmt/backend/loader/grub2.pyR s cCs|ii||dS(s7Save the menu configuration to stable storage. N(RR(RRR((s-../../common/bootmgmt/backend/loader/grub2.pyR scCs*|ot|do |iShSdS(sConvert boot instance to a dictionary suitable for serialization in the menu.conf file. The bulk of the work is performed by methods tailored for each type of BootInstance. tserialization_dictN(thasattrR(R((s-../../common/bootmgmt/backend/loader/grub2.pyR s cCsddk}t|i|d}|ot|}d|jo |d=nd|jo/t|dtjot|d|d' must be escaped (replaced with '>>'). t>s>>(Rtescape_str_for_grub_cfgR(trawstrtescstr((s-../../common/bootmgmt/backend/loader/grub2.pytescape_title_str_for_grub_cfgo scCs(|idd}|idd}|S(sFEscape a string so it evaluates to its raw value in grub.cfg. s\s\\Rs\"(R(R$t cookedstr((s-../../common/bootmgmt/backend/loader/grub2.pyR#y sN(RRRRRRRRRRRR?RR{RRRRRRRR&R#(((s-../../common/bootmgmt/backend/loader/grub2.pyR; s"     " M  !  2  RcBseZdZddedZdZdZddZddZ ddZ ddZ dd Z d Z ed Zd Zd ZddZRS(s7Emits GRUB menuentry blocks for the grub.cfg file. cCstt|i|pti|_n ||_d|_d|_h|_d|_ ||_ |pt i |_nt||_dS(sIf fileobj is None, STDOUT is used. vardict is the dictionary that holds variables that may be used by the menu entry generators. If it's None, os.environ is used. If force_grub2 is True, we instantiate the BootConfigs with a loaderclass keyword arg to ensure we get the BootInstances from GRUB2 and not a different (perhaps higher-ranked) BootLoader, whose BootInstances may be in the BootConfig's boot_instances list. RN(RRRtsysRt_fileobjtmenuentry_theme_stringtsubmenu_theme_stringt _rpool_propsR?tlzfsht force_grub2ROR?t_vardictR*(RtfileobjtvardictR.((s-../../common/bootmgmt/backend/loader/grub2.pyR s       cCst||}|ii|djoh|i|R?R RRt ValueErrorRBR (RR-trpooltzphtrawguidthexguidtvalerr((s-../../common/bootmgmt/backend/loader/grub2.pytcache_zpool_props s cCsrd}tiidotidid}ntiid ptiddjo t}nd}ti}t|_ x|D]}|o||joqn|i oht d6}|i dnd}t i|d|ii}zS|~}|i|i |x|iD]}|oAt|to1t|dd} | o| |joq%qsn|ip |iioC|iid t i|iid t i|iid Pq%q%Wxv|iD]k}|oAt|to1t|dd} | o| |joqq)n|i||iid qW|iid t iddig} |D]} | io | | ququ~ } |i || } |iid| d| }|iid|d|}|iid|||i!f|iid|iid|iid|iid WdQXqWt"|i d|_ dS(sEmit entries to the fileobj specified in __init__. This should only be invoked when this class is instantiated by the GRUB2 autogen script. R8t;R9R{t loaderclasss%Forcing loaderclass = GRUB2BootLoadert init_argdictRsif [ -f $prefix/%s ]; then ssource $prefix/%s sfi s s$if [ "$target" = "%(bios)s" ]; then troot_Rs %s s($%s)/@/boot/grub/menu.lsts if [ -s "%s" ]; then s$Legacy GRUB Menu (from root pool %s)s submenu "%s" "%s" %s{ s& extract_legacy_entries_source "$2" s } s fi N(#R?ROR?thas_keyRR"tlibbe_pytbeGetRootPoolListR R-R.R'RBtlibbetget_boot_configt__exit__t __enter__R8RRRRrRRRR)RRRR%RQtisalnumt_search_cmd_for_poolR+R (Rt zpool_listRtall_root_poolsR3targdictRtbootconfRRt_[2]Rtrootvart search_cmdtlegacy_cfg_fileR((s-../../common/bootmgmt/backend/loader/grub2.pyt emit_entries sz     ,              ?     c Csqt|d|iid}|ot|ddo ti|i}d}|io|idoti }|i i d||iddt |iddjo8x5|iddD]}|i i d||qWn|i i dd }t }nt}d} |io'd d d itt|i} n|d ||i| f} |i i | |||} xK| D]C} | djo|i i dq|i i |d | dqW|i i |d|oX|i i d|i i d||i i d|i i d|i i dqmn/|id|iitt|ddfdS(sJCall the BootInstance-specific function to emit a menuentry block RRRisif [ "$target" = "%s"is -o "$target" = "%s"s ]; then s s --users s%s t,smenuentry "%s" %s%s{ s s} selse s9 menuentry "Entry [%s] not supported on this firmware" { s echo "Not supported" s } sfi s2Not emitting entry for instance type %s (title=%s)N(RrRRR?RR#RtTARGETR'R%R)RRRR{RRQtmapRxR*RB( RRRRt clean_titlettabsttargdictt targstringt needclosetauthstrt menu_startRR((s-../../common/bootmgmt/backend/loader/grub2.pyR sV       $     R1cCs\|ii|o7|i|ito |i|t}d||fSd||fSdS(s^Returns a string containing the search command to use for the specified pool. s(search --no-floppy --fs-uuid --set=%s %ss&search --no-floppy --label --set=%s %sN(R,R>R(RR3tvarnametguid((s-../../common/bootmgmt/backend/loader/grub2.pyRE= s cCsg}t|dd}t|tp2|ido|idqZ|idn|io |ind}|o|idd}n|i||d|S( s?Emits a menuentry for a Solaris network boot instance. t _bootconfigR+s insmod efinets insmod pxeRt$s\$N( RrR?RRR0R@tkargsRt_write_menuentry_generic(RRRRR<R]((s-../../common/bootmgmt/backend/loader/grub2.pyt'_write_menuentry_SolarisNetBootInstanceK scCsg}t|dd}t|dd}t|tp|idn|io |ind}|i||}|o|i|n|i||d|S(s<Emits a menuentry for a ODD-based Solaris instance. R[Rosinsmod iso9660RN(RrR?RRR@R]RR^(RRRRR<RoR]Ry((s-../../common/bootmgmt/backend/loader/grub2.pyt'_write_menuentry_SolarisODDBootInstancee sc Cswg}|id|id|id|idt|dd}t|dd}|io |ind}|idjo:d}|i||}|o|i|nt} n+|i|||\}}} |pdS|ok|ody|it i } Wnt j oq^X|i t ijo!| t ijo|id q^n|i||||| S( s5Custom emitter for a SolarisDiskBootInstance sinsmod part_msdossinsmod part_sunpcsinsmod part_gptRR[RoRpNt load_video(R@RrR?R]RVRR{t#_handle_zfs_SolarisDiskBootInstanceRRRRR@RRCRR^( RRRRR<RoR]trootpathRyt is_encryptedR((s-../../common/bootmgmt/backend/loader/grub2.pyt(_write_menuentry_SolarisDiskBootInstance{ s8      cCspt|ddo |i}nd}| o|o|iti}n|o d|S|iddSdS(sReturns a search command string that includes the identifying file from either the bootinst (tried first) or boot_loader. t identfiles%search --no-floppy --file --set=root s%no identifying file -- search omittedN(RrR?RfRRRRB(RRRot ident_file((s-../../common/bootmgmt/backend/loader/grub2.pyR s   c Csti|}|iid}|o-|ddjod|}nd|}ny|ihdd6}Wntj o|i}nXy|ihdd6}Wntj o|i}nX|idd jp|idd joE|id |id |id |id |idn|od} d} n d} d} |id||o|id||id| ||f|o|i|n|idd||f} |id| |id| | fn|id} | djo|| } nd} |id|id| | |f|o|i|n|id|id||id| |f|S(sGGeneric code for finishing a Solaris boot instance's menuentry R}iRs"%s"sset gfxpayload=%stamd64tkarchs$ISADIRisif cpuid -l; thens set ISADIR=amd64Rs set ISADIR=RR,R-s $multiboots$modules set kern=%ss"echo -n "Loading ${root}%s$kern: "s%s %s/$kern $kern %ss insmod gzios%s%ssecho -n "Loading ${root}%s: "s%s %ss /platforms$kerns echo -n "Loading ${root}$kern: "s%s $kern %s %s( RR#R/R>tkerneltKeyErrort boot_archiveRR@(RRRRcR]Rdtgfxpayload_modesRjRlR.R/tbootarch_stringRt ba_rel_kern((s-../../common/bootmgmt/backend/loader/grub2.pyR^ s`         cCs|o |}n$|ot|i|}nd}|oCt|i|o0|id|id||idtStS(sChecks if the specified dataset (or implied dataset) has encryption enabled, and if so, emits the proper commands to prompt for and set the zfs key. Returns True if the dataset is encrypted. sinsmod zfscrypts"echo -n "[Encrypted dataset %s] " tzfskeyN(RR-R?R R@RR{(RR3RRt dataset_name((s-../../common/bootmgmt/backend/loader/grub2.pyt_handle_zfs_encrypted_datasets   c Cst|dd }|ot|\}}nt|dd }|p|idd S|id|id|i|}|o|i|n|i|||}|od|} |id| n|idd } |o|id }nd }|| |fS( snHandle the ZFS-specific part of menuentry generation. Returns the kargs to use in the entry. RR3s0# Cannot determine the root pool for this entry.s insmod zfsRs /ROOT/%s/@szfs-bootfs %s/ zfs_bootfss/zfs-defaultbootfs $root zfs_rootpath zfs_bootfss/${zfs_rootpath}/@s -B $zfs_bootfss-B $zfs_bootfsN(RrR?RR@RERrR( RRRR]RR3tbenameRLRdRc((s-../../common/bootmgmt/backend/loader/grub2.pyRbs,     c Csg}|idjpt|itj pt|idjpt|idtj pt|idjo4t|idtj ot|idtj pJt|idjoSt|idtjo9t|iddjo|id|id|Sdt|id}t|idjo;t|idtjox|idD]}y(t|}|dt|d7}Wqdt j opt |t oYt|djoF|djo9|d jo,t |t dd}|d |7}qqdXqdWqwy/t|id}|dt|d7}Wqwt j o|d|id7}qwXn|d 7}|id ||i o|id |nt|idjo!|id|i|ifn|id|i|S(s3Custom emitter for a ChainDiskBootInstance iiis)Invalid chainloader info in boot instances(# Could not process this chainload entrys(hdROtatzs,%dt)s set root=%ssparttool %s boot+schainloader --force %s+%sschainloader --force +%sN(t chaininfoR?RRRRRBR@RxR2RRtordt forceactivet chainstartt chaincount(RRRRtdiskstrt tuple_itemtint_itemtpart((s-../../common/bootmgmt/backend/loader/grub2.pyt&_write_menuentry_ChainDiskBootInstanceBsN,&$0        N(RRRR?R{RR8RNRRER_R`ReRR^RrRbR(((s-../../common/bootmgmt/backend/loader/grub2.pyR s  [ 2    4  B  'cCstgS(sTReturns a list of boot loader classes, consumed by the boot loader factory. (R'(((s-../../common/bootmgmt/backend/loader/grub2.pytbootloader_classes|s(HRRRRR/RR@R>ROtpkg.pkgsubprocesst pkgsubprocessRRRWRdRR(R,RR RRRRRRRRRtbootmgmt.pysolR R R R R RRRRRtbootmgmt.bootloaderRRR RRRRRtbootmgmt.bootutilRRRRRRR R!R"tbootmgmt.bootinfoR#t bootmgmt.backend.loader.authconfR$t bootmgmt.backend.loader.menuconfR%R&t EFISYS_PARTIDt EFISYS_GUIDR'RRR(((s-../../common/bootmgmt/backend/loader/grub2.pytsT               @F(@I