iVc@sfdZddkZddkZddkZddkZddkZddklZlZl Z l Z l Z ddk l Z lZddklZlZlZlZlZlZddklZddklZddklZlZlZlZlZlZl Z l!Z!l"Z"l#Z#dd k$l%Z%l&Z&d e e fd YZ'd efd YZ(dZ)dS(s6 Legacy GRUB BootLoader Implementation for pybootmgmt iN(t MenuDotLstt MenuLstErrortMenuLstMenuEntrytMenuLstCommandtMenuLstBootLoaderMixIn(t BootLoadertBootLoaderInstallError(t BootConfigtDiskBootConfigt NetBootConfigt BootInstancetSolarisDiskBootInstancetSolarisNetBootInstance(tChainDiskBootInstance(tget_current_arch_string( t BootmgmtErrortBootmgmtArgumentErrort!BootmgmtUnsupportedOperationErrortBootmgmtInterfaceCodingErrort!BootmgmtIncompleteBootConfigErrortBootmgmtConfigReadErrortBootmgmtConfigWriteErrort#BootmgmtMalformedPropertyValueErrortBootmgmtNotSupportedErrort BootmgmtUnsupportedPropertyError(tPopentCalledProcessErrortLegacyGRUBBootLoadercBsreZdZdZhd>d6ZdZdZdedeZdZdZ d Z d Z h d d 6d e e d6dd6dd6ded6de d6de d6dd6dd6Z dZdZeieieieieieieieigZheiei6ZdZedZed Zed!Z ed"Z!ed#Z"d$Z#ed%Z$ed&Z%ed'Z&d(Z'e(d)Z)d?d*Z+e,d+Z-e,d,Z.d-Z/d.Z0d/Z1d0Z2d1Z3d?d2Z4d3Z5d4Z6d5Z7d6Z8d7Z9d8Z:d9Z;d:Z<d;Z=e>d?d?d<Z?d=Z@RS(@sImplementation of a Legacy GRUB (GRUB 0.97) BootLoader. Handles parsing the menu.lst file (reading and writing), though reading it and creating BootInstance objects is rather fragileitbiostx86smenu.lsts boot/grubt/s/boot/grub/splash.xpm.gzit343434tF7FBFFs default 0tdefaultstimeout ttimeouts # serial --unit=0 --speed=9600tserials# terminal serialtterminals# splashimage t splashimages# foreground t foregrounds# background t backgroundt#t min_mem64t hiddenmenuiis# default menu entry to boot %(default)s # # menu timeout in second before default OS is booted # set to -1 to wait for user input %(timeout)s # # To enable grub serial console to ttya uncomment the following lines # and comment out the splashimage line below # WARNING: do not enable grub serial console when BIOS console serial # redirection is active. %(serial)s %(terminal)s # # Uncomment the following line to enable GRUB splashimage on console %(splashimage)s %(foreground)s %(background)s # # To chainload another OS # # title Another OS # root (hd,) # chainloader +1 # # To chainload a Solaris release not based on GRUB: # # title Solaris 9 # root (hd,) # chainloader +1 # makeactive # # To load a Solaris instance based on GRUB: # # title Solaris # bootfs /ROOT/ # kernel /platform/i86pc/kernel/amd64/unix # module /platform/i86pc/amd64/boot_archive # # To override Solaris boot args (see kernel(1M)), console device and # properties set via eeprom(1M) edit the "kernel" line to: # # kernel /platform/i86pc/kernel/amd64/unix -B prop=value,... # %(hiddenmenu)s %(min_mem64)s cKs<|id}|djp|idjodSt}|itijo|djo|iddS|itijo|idj ot i |S|iti jot i |S|itijoTy|i ||idWn&tj o}|id|dSXt i|Std|idS(sIProbe for Legacy GRUB files for use with the BootConfig passed int bootconfigRs6Legacy GRUB boot loader not supported on this platformtfwtypes#[PROBE ABORTED DUE TO EXCEPTION] %ssBoot class %s not supported.N(tgettNonet boot_classRRtBOOT_CLASS_NETt_debugtBOOT_CLASS_DISKt boot_fstypeRt _probe_disktBOOT_CLASS_ODDt _probe_oddt_validate_platform_and_firmwareRt _probe_netR(tclstkwargsR+tcur_archtbmerr((s2../../common/bootmgmt/backend/loader/legacygrub.pytprobes.    cKsc|id}|i}|id|y|i|dgWntj odSXt|S(sThis Legacy GRUB probe function searches the ODD's root, looking for the Legacy GRUB menu.lst and stage1 and stage2 filesR+sodd_image_root=%ssboot/grub/stage2_eltoritoN(R-tget_rootR1t_probe_genericRR.R(R9R:R+troot((s2../../common/bootmgmt/backend/loader/legacygrub.pyR6s cKs>|id}|i|}|pdS||d|id}|i|}|pdS||d] s data root=%ssboot/grub/pxegrubiN(R>R1R?RtARTIFACT_BOOTLOADER_IMAGEStARTIFACT_BOOTLOADER_TOOLSRR.RERFRGt net_data_rootRt MENU_LST_FILEt pxe_suffixtstattS_ISREGtst_modetst_sizetARTIFACT_BOOTLOADER_CONFIGFILEStOSError(R9R+R@RAtmenu_lstt stat_info((s2../../common/bootmgmt/backend/loader/legacygrub.pyRBs& #c Cs|i}t|dd }|o|i}n |i}|djo |}n/|djo |i}n|id|gStii |p|idgS|id||fg}y*|i |t i g|t ig7}Wn+tj o}|idt|nXy*|i |dd g|t ig7}Wn+tj o}|idt|nXyWd }tii|o*ti|tio|t ig7}n|id |Wn%tj o} |id | nX|S(s=Probe for menu.lst, stage1, stage2, and installgrub. t boot_loadertufstzfssUnknown filesystem type: %ssdataroot is not a directorysdataroot=%s cfgdataroot=%ss3Problem checking GRUB Legacy boot loader images: %ssboot/grub/stage1sboot/grub/stage2s/usr/sbin/installgrubs%s not found or not executables-Error while looking for GRUB Legacy tools: %sN(R3tgetattrR.t_get_boot_loader_data_rootR>tzfstopR1RERFtisdirR?Rt_MENU_LST_PATHRRbRRKRYtexiststaccesstX_OKRZRc( R9R+tfstypet bootloaderRLt cfgdatarootRAtbmnsetfull_exec_pathtoserr((s2../../common/bootmgmt/backend/loader/legacygrub.pyRC+sN             cCsF|itijo|i|S|itijo|i|SgS(svReturns a list of artifacts for this BootLoader, given a bootconfig to use for directory information. (R/RR2RCR0RB(R9R+((s2../../common/bootmgmt/backend/loader/legacygrub.pytprobe_artifactses cCs]tt|it|ito|iitint i |it i Load boot instances and GRUB properties from the menu.lst files+load_config() is not supported for class %sN(RzR/RR2RERFRGt_menu_lst_dir_diskR\R0R[RR]Rt __class__t__name__t_load_config_commontadd_boot_instancetFalsetdirty(RXtdo_addRdtboot_instances((s2../../common/bootmgmt/backend/loader/legacygrub.pyt load_configs cCs|idjo-dt|}|i|t|n|iitijo|i|S|iiti jo|i |S|iiti jo|i |St ddS(sThe only file that needs to be written is the menu.lst file, using information from the BootConfig instance to which we have a reference. Information from the boot loader's properties is also used to determine which commands are emitted at the global levels/Cannot _write_config(%s) - _boot_config is Nones XXX - Fix MeN(RzR.RKR1RR/RR2t_write_config_diskR5t_write_config_oddR0t_write_config_netR(RXtbasepathtplatdicttmsg((s2../../common/bootmgmt/backend/loader/legacygrub.pyt _write_configs  cCs|ip|iS|ii}|tijo/tii|iit i |ii }n~|ti jo+tii|ii t it i }nC|tijo"tii|it i }ntd||id||f|S(s~Returns the ultimate destination of menu.lst, depending on the type of BootConfig stored in self._boot_config sUnknown BootConfig class %ss+Boot class %s detected. MENU_LST_PATH => %s(RzRmR/RR0RERFRGtnet_tftproot_subdirRR\R]R5R>tMENU_LST_SUBDIRR2RRR1(RXR/t menu_lst_path((s2../../common/bootmgmt/backend/loader/legacygrub.pyt MENU_LST_PATHs(       cCs)|iitijo |iSdSdS(Ns /boot/grub(RzR/RR2R(RX((s2../../common/bootmgmt/backend/loader/legacygrub.pyt config_dirs cCs|ii}|djo!|djotd|n|djo|ii}n!|djo|ii}ntii|ti S(NRhRgsUnknown filesystem: %s( RzR3RRkR>RERFRGRR(RXRqt menu_lst_root((s2../../common/bootmgmt/backend/loader/legacygrub.pyRs   c CsG |id|yt||_WnXtj o}td||n2tj o%}td|t|fnXt}d-}g}x|ii D]}t |t o1h}|i dd-j p|i dd-j ox|i D]}t |tpqn|idjodi|i|dRRRRRRRRRRmRttempfiletNamedTemporaryFileRRItshutiltcopyRRRJRtOUTPUT_TYPE_BIOS_ELTORITO(RXRtodd_rootRRRttmpfileR((s2../../common/bootmgmt/backend/loader/legacygrub.pyRs8       c Cs;|djotdn|id||i||i}xt|D]\}}|tipqOnt|}t i }|tii |djoti |ti %ssboot/grub/pxegrubN(R.RR1RRRRRRRR\tfindtOUTPUT_TYPE_NETCONFIGRR tTOKEN_TFTP_ROOTRtOUTPUT_TYPE_BIOS_NBPRERFRGRztnet_osimage_root(RXRRRRt menulstfile((s2../../common/bootmgmt/backend/loader/legacygrub.pyRs2      c Cstii}|iiti}|dj odt||d %ssAdding global commands: %sN(tsetRSRRyRRtaddR.t delete_entityRRtset_argsR1Rt differenceRKt add_global( RXRtglobal_cmd_entitiest deleted_cmdsRRt cmd_and_argstsplit_cmd_argsRRtcmdlisttmissing_globalst missing_cmd((s2../../common/bootmgmt/backend/loader/legacygrub.pyRs6        6 cCs|ii}d|}t|i|d}|dj o8|idj o|iid|in|||S|id||f|idj odSdSdS(sUse the BootInstance's class name to find the entry-generator method. Entry generator functions are responsible for producing a string with the rest of the entry (the title is printed by the caller)t_generate_entry_Rs$No entry generator (%s) for class %sRN(RRRiR.Rtupdate_commandRR1(RXtinstancet instclsnamet method_nametentry_generator((s2../../common/bootmgmt/backend/loader/legacygrub.pyR s      c Cs\|djodn|}t|tid}t|tid}t|tid}|idjoU|od|}nd}|od|}nd}|od|}qd}nVd}|o|d|7}nd}|od|}nd}|od|}ny|ihd d 6|_Wn%tj ot d |inXd |ijp d |jod |i} nd|i} | |djpdnd|7} y|i hd d 6|_ Wn%tj ot d|i nXd |i jp d | jod|i } nd|i } |idj ox|||| | fD]}} | i dd} t | djo|ii | qWt | djo+|ii| d| didtqWqWWdSd} |dj o| |d7} n|dj o| |d7} n|dj o| |d7} n| | d7} | | 7} | S(NRs splashimage s foreground s background R%RR&R's$ISADIRtkarchRt$skernel$ skernel Rsmodule$ smodule iiitcreates (R.RiRRRRRRtKeyErrorRRRRtdelete_commandR'RR(RXRRR RRt splash_cmdtfore_cmdtback_cmdt kernel_cmdt module_cmdtnextcmdt nextcmd_argstostr((s2../../common/bootmgmt/backend/loader/legacygrub.pyt_generate_entry_generic&sz  "     cCs4|i||ii}|idjo|SdS(s N(R9RRRR.(RXRR8((s2../../common/bootmgmt/backend/loader/legacygrub.pyt&_generate_entry_SolarisNetBootInstancesc Csd}d}d}d}|idjo|idjo |idjotdn|idj o|d|i7}n|idj o|idj o|iid}|dj odi|i}|i doi|i d}t |d joC|i d |d |d |i7}di|g|d }qJqNqRn|djo|d |i7}qxn|i djo d}q|i iddjod|i }q|i }n4|i dj o#|i idjo |i }n|idj oxt||fD]f} | i dd } t | d jo|ii| q|ii| d| d idtqW|i||dS|i||}d} |djo|d} n|djo| |d7} n| |}|S(sCMenu-entry generator function for SolarisDiskBootInstance instancesRRRRhs'bootfs and rpool properties are missingRt(Risreusing findroot hint: %sis (pool_s pool_s-B $ZFS-BOOTFSs $ZFS-BOOTFSis-B $ZFS-BOOTFS iR.s N(RqRR.RRRRRGRRRRR1RRRR0R'RR9( RXRR8Rt bootfs_cmdt findroot_cmdt findroot_origtfindroot_orig_argstfindroot_componentsR6tcmd_argst prepend_cmds((s2../../common/bootmgmt/backend/loader/legacygrub.pyt'_generate_entry_SolarisDiskBootInstancesd        &      cCs|i||iS(N(R9R(RXR((s2../../common/bootmgmt/backend/loader/legacygrub.pyt&_generate_entry_SolarisODDBootInstancesc CsZ|idjotdnt|itj pt|idjotdnt|idtj otdnt|idjoDt|idtj o*t|idtj otdnt|idjoDt|idtjo*t|iddjotdnd t|id}t|idjoit|idtjo0xH|idD]}|d t|7}qWq|d t|id7}n|d 7}|i o!|i i d od |}n d|}d}|i o4|i o |i i ddgdt qtd}n"|i o|i i ddnd}t|idjo|tt|i7}n|dtt|i7}|i dj oUxM||fD]?}|idd}|i i |d|didt qWdS|d|} |o| d|7} n| S(s Menu-entry generator for ChainDiskBootInstance instances. This is a VERY simple use of the rootnoverify and chainloader Legacy GRUB commands. Chainloading is only supported to a specific, numbered drive, partition specification, and physical sector offset/count.schaininfo property is missingis)chaininfo must be a non-zero-length tupleschaininfo[0] must be an intis$chaininfo[1] must be an int or tupleis$chaininfo[1] must not have > 2 itemss(hdRt)R@sroot s rootnoverify t makeactiveRR.s chainloader t+Rs N(RR.RttypeRRRRRKRRt forceactiveR'Rt chainstartt chaincountRR( RXRtdiskstrt tuple_itemtroot_cmdt active_cmdtchainloader_cmdR6RAR8((s2../../common/bootmgmt/backend/loader/legacygrub.pyt%_generate_entry_ChainDiskBootInstances`,0         cCs|i}|pdS|i}dgti}x"|D]}|id p d|joq;n|did}|ddjo ti}n|ddjo ti}n|ddjo ti}nu|dd joBti }hd d 6d d 6dd6}|i |dd |d,,, |

,,). | is currently defined to be a | number (valid valid 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). iRYRXR[RZR]R\s!Bad parity value in serial_paramsthwtHtswtSs'Bad flow control value in serial_paramsiRRN(RRNNNNN( RRRRRR/R1R.t PROP_SP_FLOWCRRRR(RXRRWtflowct ret_params((s2../../common/bootmgmt/backend/loader/legacygrub.pyRGs:  !       cCsIx'|iiD]}|iiddq Wtt|i||||S(NR(RzRt__dict__t setdefaultR.RTRtinstall(RXtlocationtforcet verbose_fileRR((s2../../common/bootmgmt/backend/loader/legacygrub.pyRns  c Cs(t|itp|iddSt|djo"|ddjo|dip2t|djo|ddjo|diptd |nd g}|idj o|d |ig7}n|o|d g7}nt|t o$|i t i o|d g7}n||d|d|g7}|iddi |d}zVy%ti|dtidti}Wn*tj o}|id|i|i}|itijod} |io{|iip |iioaddi |} |iio| d|ii7} n|iio| d|ii7} qNntd|dt|i| qn4tj o'} td|dt| nXWd|oj|oc|ddi |IJ|io|d|iIn|io|d|iIn|dIJnXdS(spInvoke installgrub to write stage1 and stage2 to disk. Slice nodes (and only slice nodes) are required.s/Ignoring _write_loader() for non-DiskBootConfigNiitsiiisDevice node is not a slice: s/sbin/installgrubs-us-Fs-ms/boot/grub/stage1s/boot/grub/stage2s#_write_loader: Invoking command: %sRtstdouttstderrs_write_loader: Return code = %dRs Output from "%s" was: s : %ss : %ssinstallgrub failed for device s: Return code s4Error while trying to invoke installgrub for device s: sOutput from "%s" was:s(RyRzRR1RtisdigitRtversionR.RR-Rt PLATOPT_MBRRGRt check_calltSTORERt returncodetpopenRtINSTALLGRUB_NOUPDTRtRsRKRc( RXtdevnamet data_rootRpRqRRtpobjtcpetoutputtose((s2../../common/bootmgmt/backend/loader/legacygrub.pyt _write_loadersb $$ #   $  *$  (sbiosN(ARt __module__t__doc__tWEIGHTtSUPPORTED_PLATFORMSR\RRmRtDEFAULT_TIMEOUTRRRKRR|tINSTALLGRUB_NOEINFORR~RRRRRRRtSUPPORTED_PROPSRR|Rt classmethodR=R6R8R4R?RURBRCRwRxRRR.RtpropertyRRRRRRRRRRR9R:RCRDRQRRRRnR(((s2../../common/bootmgmt/backend/loader/legacygrub.pyR9s      4# :   ! . . ( ,  `  E  F , ; RcBseZddZdZRS(s/boot/solaris/menu.lstcCstt|i|dS(N(RTRRU(RXtfilename((s2../../common/bootmgmt/backend/loader/legacygrub.pyRUscCsdS(s Command := Keyword Arguments | VarName '=' Value Arguments := Arguments [ ]+ Argument | Argument Keyword := 'blocklist' | 'boot' | 'bootfs' | 'bootp' | 'cat' | 'chainloader' | 'cmp' | 'color' | 'configfile' | 'debug' | 'default' | 'device' | 'dhcp' | 'displayapm' | 'displaymem' | 'embed' | 'fallback' | 'find' | 'findroot' | 'fstest' | 'geometry' | 'halt' | 'help' | 'hiddenmenu' | 'hide' | 'ifconfig' | 'impsprobe' | 'initrd' | 'install' | 'ioprobe' | 'kernel$' | 'kernel' | 'lock' | 'makeactive' | 'map' | 'md5crypt' | 'min_mem64' | 'module$' | 'module' | 'modulenounzip' | 'pager' | 'partnew' | 'parttype' | 'password' | 'pause' | 'quit' | 'rarp' | 'read' | 'reboot' | 'root' | 'rootnoverify' | 'savedefault' | 'serial' | 'setkey' | 'setup' | 'terminal' | 'terminfo' | 'testload' | 'testvbe' | 'tftpserver' | 'timeout' | 'title' | 'unhide' | 'uppermem' | 'vbeprobe' Argument := [^ ]+ VarName := [A-Za-z0-9]+ Value := [^ ]+ N((RX((s2../../common/bootmgmt/backend/loader/legacygrub.pyt_analyze_syntaxs(RRRUR(((s2../../common/bootmgmt/backend/loader/legacygrub.pyRs cCstgS(N(R(((s2../../common/bootmgmt/backend/loader/legacygrub.pytbootloader_classess(*RRRRER^Rtbootmgmt.backend.loader.menulstRRRRRtbootmgmt.bootloaderRRtbootmgmt.bootconfigRRR R R R R tbootmgmt.bootutilRtbootmgmtRRRRRRRRRRtsolaris_installRRRRR(((s2../../common/bootmgmt/backend/loader/legacygrub.pyts(     (.F #