Dictionaries/Dict.OS/Includes/Bootloader/Includes/Bootloader.Grub2.psm1
<#
.SYNOPSIS Search for a grub configuration .DESCRIPTION Search into local partition for a grub.cfg file. Default search for a "grub.cfg" file. If config name is overriden, use -Filename to search for custom filename. .EXAMPLE Find-OSBootloaderGrub2Cfg -Path "/boot" .EXAMPLE Find-OSBootloaderGrub2Cfg -Path "/boot" -Filename "mygrub.cfg" .NOTES General notes #> function Find-OSBootloaderGrub2Cfg { [CmdletBinding()] [OutputType([String])] Param ( # Path to start search [Parameter(Mandatory = $true, ValueFromPipeLine = $true)][string]$Path, # Custom filename to search for [Parameter(Mandatory = $false, ValueFromPipeLine = $false)][string]$Filename = "grub.cfg", # Search as far as MaxDepth deep [Parameter(Mandatory = $false, ValueFromPipeLine = $false)][uint32]$MaxDepth = 3 ) Begin { Write-PwShFwOSEnterFunction } Process { $grubcfg = Get-ChildItem -Path $Path $Filename -Recurse -Depth $MaxDepth -ErrorAction SilentlyContinue return ${grubcfg}?.fullname } End { Write-PwShFwOSLeaveFunction } } function Get-OSBootloaderGrub2DefaultBoot { [CmdletBinding()] [OutputType([String])] Param ( [Alias('ConfigFile')] [Parameter(Mandatory = $false, ValueFromPipeLine = $false)][string]$Grub2Cfg = "/boot/grub/Grub2.cfg" ) Begin { Write-PwShFwOSEnterFunction } Process { $rc = (Get-Content $Grub2Cfg | select-string "^LABEL") | ForEach-Object { $_ -match "^LABEL\s*(?<label>\w+)" } if ($rc) { return $Matches.label } else { return $null } } End { Write-PwShFwOSLeaveFunction } } function Set-OSBootloaderGrub2DefaultBoot { [CmdletBinding()] [OutputType([System.Boolean])] Param ( [Alias('ConfigFile')] [Parameter(Mandatory = $false, ValueFromPipeLine = $false)][string]$Grub2Cfg = "/boot/grub/Grub2.cfg", [Parameter(Mandatory = $true, ValueFromPipeLine = $false)][string]$label ) Begin { Write-PwShFwOSEnterFunction } Process { $Grub2 = (Get-Content $Grub2Cfg -Raw) -replace "^DEFAULT .*", "DEFAULT $label" $Grub2 | Out-File $Grub2Cfg return $? } End { Write-PwShFwOSLeaveFunction } } function Get-OSBootloaderGrub2BootEntries { [CmdletBinding()] [OutputType([String])] Param ( # Custom filename to search on [Parameter(Mandatory = $true, ValueFromPipeLine = $true)][string]$Filename, # Show all entries label [Parameter(Mandatory = $false, ParameterSetName = 'ALL')][switch]$All ) Begin { Write-PwShFwOSEnterFunction } Process { $menuEntries = @() # $submenuEntries = @() if (Test-FileExist $Filename) { # parse grub.cfg # To extract correct §, we need to read the file with -Raw parameter # (?ms) sets regex options m (treats ^ and $ as line anchors) and s (makes . match \n (newlines) too`. # ^## .*? matches any line starting with ## and any subsequent characters *non-greedily* (non-greedy is '.*?' set of characters at the end of pattern). # -AllMatches to get... well... all matches $content = Get-Content -Raw $Filename | Select-String -Pattern '(?ms)^menuentry .*?^}$' -AllMatches # Write-PwShFwOSDevel "MESSAGES = " + $MESSAGES.Matches[0] # Write-PwShFwOSDebug "MESSAGE = $MESSAGE" foreach ($msg in $content.Matches) { $menuEntry = [PSCustomObject]@{} $menuEntry | Add-Member -MemberType NoteProperty -name "Bootloader" -Value "grub2" $menuEntry | Add-Member -MemberType NoteProperty -name "Filename" -Value $Filename if ($msg.value -match "^menuentry '(?<label>.*?)' .*") { $menuEntry | Add-Member -MemberType NoteProperty -name "Label" -Value $Matches.label } if ($msg.value -match "`n\s*linux\s*(?<kernel>.*)") { $menuEntry | Add-Member -MemberType NoteProperty -name "kernel" -Value $Matches.kernel } if ($msg.value -match "`n\s*initrd\s*(?<initrd>.*)") { $menuEntry | Add-Member -MemberType NoteProperty -name "initrd" -Value $Matches.initrd } $menuEntries += $menuEntry } } else { return $null } return $menuEntries } End { Write-PwShFwOSLeaveFunction } } <# .SYNOPSIS Abalyze grub.con file and return an object .DESCRIPTION Load a grub.con file into an object. All parameters are kept as is. Menuentries are stored in an array. .EXAMPLE $grub2 = Get-OSBootloaderGrub2Object -Filename /boot/grub/grub.con .NOTES General notes #> function Get-OSBootloaderGrub2Object { [CmdletBinding()] [OutputType([PSCustomObject])] Param ( # Full path to grub.con to load [Parameter(Mandatory = $true, ValueFromPipeLine = $true)][string]$Filename ) Begin { Write-PwShFwOSEnterFunction } Process { $grub2 = @{} # $content = (Get-Content $Filename | Select-String -Pattern "^[a-zA-Z_0-9]+" -AllMatches | Select-String "menuentry" -NotMatch) -replace '(^[a-zA-Z_0-9]+)', '${1} = ' | ConvertFrom-StringData # foreach ($key in $content.keys) { # $grub2.Add($key, $content.$key) # } # $content = (Get-Content $Filename | Select-String -Pattern "^[a-zA-Z_0-9]+" -AllMatches | Select-String "menuentry" -NotMatch) -replace '(^[a-zA-Z_0-9]+)', '${1} = ' | ConvertFrom-StringData foreach ($line in (Get-Content $Filename)) { if ($line -match "^(?<key>[a-zA-Z_0-9]+)\s(?<value>.*)") { $key = $matches.key $value = $matches.value switch ($key) { 'menuentry' { continue } Default { if ($grub2.$key) { if ($grub2.$key -is [array]) { $grub2.$key += $value } else { $oldValue = $grub2.$key $grub2.$key = @($oldValue, $value) } } else { $grub2.$key = $value } } } } } # $entries = (Get-Content -Raw $Filename) -split '\r?\n\r?\n' -match '^menuentry' # $menuentries = @() # foreach ($entry in $entries) { # $menuentry = @{} # # flatten menuentry # $flatEntry = (($entry -split '\n' -replace '^\s+') -replace '\\', '/' | Select-String "^#" -NotMatch -AllMatches) -replace ' {' -replace '}' # # convert to hashtable # $hash = $flatEntry -replace '(^[a-zA-Z_0-9]+)', '${1} = ' | ConvertFrom-StringData # foreach ($key in $hash.keys) { # $menuentry.Add($key, $hash.$key) # } # $menuentries += $menuentry # } $menuentries = @() $entries = Get-Content -Raw $Filename | Select-String -Pattern '(?ms)^menuentry .*?^}$' -AllMatches # Write-PwShFwOSDevel "MESSAGES = " + $MESSAGES.Matches[0] # Write-PwShFwOSDebug "MESSAGE = $MESSAGE" foreach ($entry in $entries.Matches) { $menuEntry = @{} # save raw entry definition to lose nothing $menuEntry.raw = $entry.value if ($entry.value -match "^menuentry `"(?<label>.*?)`" .*") { $menuEntry.Label = $Matches.label } $options = $entry.value | Select-String -Pattern '\n\s+(?<k>[\S.]*)\s+(?<v>.*)' -AllMatches foreach ($option in $options.Matches) { if ($option.Groups['k'].Value -like "#*") { # this is a comment continue } $key = $option.Groups['k'].Value $value = $option.Groups['v'].Value if ($menuentry.$key) { if ($menuentry.$key -is [array]) { $menuentry.$key += $value } else { $oldValue = $menuentry.$key $menuentry.$key = @($oldValue, $value) } } else { $menuentry.$key = $value } } $menuEntries += [PSCustomObject]$menuEntry } $grub2.menuentries = $menuentries return [PSCustomObject]$grub2 } End { Write-PwShFwOSLeaveFunction } } |