Blog

New toy! Odroid XU4 :)

I love these computers!

 

This week I recieved a new arm-based computer, An Odroid XU4 from Hardkernel.
This beast have a Samsung big.LITTLE processor with 4 (Cortex A15)+4 (Cortex A7) cores, 2Gb ram, gigabit ethernet, 2 USB3 ports, 1 USB2 port and HDMI out.

Top view. Look at that beautiful blue heatsink!
The size is about the same as an Raspberry Pi.
The case I bought wasn’t that good looking, but it does the job of protecting the motherboard.

My plan is to make this the new host for this site… someday.
But first I´m going to play a little with it.

In the Odroid forum you can find a lot of help and information.

Right now I`m play around a bit with Android and RetroPi.
But soon I hope to start configure WordPress on it.

Some links for more information and other stuff

Hardkernels product page for the XU4.
Armbian Linux image.
RetroPi instructions for manuall install on the XU4 and the offical Hardkernel Linux image they base the the installation on.
DietPi Linux image, partly based on Armbian.

 

Mounting ISO-files with Powershell

In windows 10 and Server 2016 you have built in support for mounting ISO-files to a virtual CD/DVD-Drive.

On my HTPC I wanted to crate a simple and functional GUI to mount and unmount ISO-files.
So I wrote a Powershell-script to manage that. It also starts PowerDVD and start to play that drive the ISO-files has been mounted on.

I’t not beautiful, but functional…
$VDrive = New-Object System.Collections.Generic.List[System.Object]
$PDVDPath = "C:\Program Files (x86)\CyberLink\PowerDVD17\PowerDVD.EXE"
$IsoPaths = "D:"#"F:\4k ISOS"
$IsoFiles = ''


#region Functions

# Refreshes the list of virtual drives
Function RefreshVCDList {
    $VDrive.Clear()
    $Drives = Get-Volume
    ForEach ($Vol in $Drives){
        $DLetter = ''
        $DLetter = $Vol.DriveLetter
        IF (Get-DiskImage -DevicePath "\\.\$DLetter`:" -ErrorAction Ignore){
            Write-host $DLetter
            $VDrive.Add($DLetter)
        }
    }
}

# Refresh the list of Iso-files
Function RefreshIsoFiles {
    $Isos = @()
    ForEach($Path in $IsoPaths){
        $Isos += (Get-ChildItem -path $Path -Recurse -Include '*.iso' -File).FullName
    }
    return $Isos
}

# Unmounts all virtual drives
Function UnMountAll {
    RefreshVCDList
    ForEach($vol in $VDrive){
        Write-Host "unmounting "\\.\$vol`:""
        Dismount-DiskImage -DevicePath "\\.\$vol`:" -ErrorAction ignore
    }
}


# Mounts selected iso-file
Function MountImageFile {
    Param(
    [Parameter(Mandatory = $true)]
    [STRING]$ImagePath
    )
    $global:Mounted = ''
    $IsAllreadyMouted = ''
    $IsAllreadyMouted = (Get-DiskImage -ImagePath "$ImagePath").Attached
    $Driveletter = ''
    Write-Host "Info mountstatus:" $IsAllreadyMouted
    IF($IsAllreadyMouted -eq $false){
        Write-Host "mounting $ImagePath"
        $global:Mounted = (Mount-DiskImage -ImagePath "$ImagePath" -PassThru | Get-Volume)
    } ELSEIF ($IsAllreadyMouted -eq $true){
        Write-Host "Image $ImagePath is allready mounted"
        $global:Mounted = (Get-DiskImage -ImagePath "$ImagePath" | Get-Volume)
    }
    [STRING]$Driveletter = $global:Mounted.DriveLetter +":"
    Write-host "Info mountvolume:" $Driveletter
    return $Driveletter
}

Function UpdateISOList {
    #$LstBoxIsos.ResetText()
    $Files = @()
    RefreshVCDList
    $Files = RefreshIsoFiles
    $LstBoxIsos.Items.Clear()
    ForEach($IsoItem in $Files){
        IF ($IsoItem -ne $null){
            $LstBoxIsos.Items.Add($IsoItem)
        }
    }
}

#endregion

#region GUI
Add-Type -AssemblyName System.Windows.Forms
$FrmMain = New-Object system.Windows.Forms.Form
$FrmMain.Text = "Markus ISO-Mounter"
$FrmMain.TopMost = $false
$FrmMain.Width = 1300
$FrmMain.Height = 800
$FrmMain.TopMost = $false
$FrmMain.Add_Resize({
    #Sets size and place of other stuff when main form changes
    $LstBoxIsos.Width = ($FrmMain.Width - 45)
    $LstBoxIsos.Height = ($FrmMain.Height - 200)

    $BtnRefresh.location = new-object system.drawing.point(10,($FrmMain.Height - 130))
    $BtnUnMount.location = new-object system.drawing.point(130,($FrmMain.Height - 130))
    $ChkBoxUnmount.location = new-object system.drawing.point(10,($FrmMain.Height - 160))
    $ChkStartPDVD.location = new-object system.drawing.point(10,($FrmMain.Height - 190))

})

$LstBoxIsos = New-Object system.windows.Forms.ListBox
$LstBoxIsos.Width = 1255
$LstBoxIsos.Height = 600
$LstBoxIsos.Font = "Microsoft Sans Serif,14"
$LstBoxIsos.HorizontalScrollbar = $true
$LstBoxIsos.Add_DoubleClick({
    $File = $LstBoxIsos.SelectedItem
    [STRING]$MountDrive = ''
    IF ($ChkBoxUnmount.Checked){
        Write-Host "unmounting all drives"
        UnMountAll
    }
    Write-Host "mounting" $File
    $MountDrive = (MountImageFile -ImagePath "$File")
    Write-Host "iso mounted on $MountDrive"
    IF ($ChkStartPDVD.Checked){
    TRY{
        Write-Host "Starting PowerDVD with $MountDrive"
        Start-Process -FilePath $PDVDPath -ArgumentList $MountDrive
    }
    CATCH{
        Write-Host "Could not start PowerDVD"
    }
    }
})
$LstBoxIsos.location = new-object system.drawing.point(10,10)
$FrmMain.controls.Add($LstBoxIsos)

$BtnRefresh = New-Object system.windows.Forms.Button
$BtnRefresh.Text = "Refresh iso-files"
$BtnRefresh.Width = 100
$BtnRefresh.Height = 60
$BtnRefresh.location = new-object system.drawing.point(10,670)
$BtnRefresh.Font = "Microsoft Sans Serif,10"
$BtnRefresh.Add_Click({
    $BtnRefresh.BackColor = "RED"
    $BtnRefresh.Update()
    UpdateISOList
    $BtnRefresh.ResetBackColor()
})
$FrmMain.controls.Add($BtnRefresh)


$BtnUnMount = New-Object system.windows.Forms.Button
$BtnUnMount.Text = "Unmount all drives"
$BtnUnMount.Width = 150
$BtnUnMount.Height = 60
$BtnUnMount.location = new-object system.drawing.point(130,670)
$BtnUnMount.Font = "Microsoft Sans Serif,10"
$BtnUnMount.Add_Click({
    $BtnUnMount.BackColor = "RED"
    $BtnUnMount.Update()
    UnMountAll
    $BtnUnMount.ResetBackColor()
})
$FrmMain.controls.Add($BtnUnMount)

$ChkBoxUnmount = New-Object system.windows.Forms.CheckBox
$ChkBoxUnmount.Text = "Unmount all drives when mouting iso"
$ChkBoxUnmount.AutoSize = $true
$ChkBoxUnmount.Width = 95
$ChkBoxUnmount.Height = 20
$ChkBoxUnmount.location = new-object system.drawing.point(10,640)
$ChkBoxUnmount.Font = "Microsoft Sans Serif,10"
$ChkBoxUnmount.Checked = $true
$FrmMain.controls.Add($ChkBoxUnmount)

$ChkStartPDVD = New-Object system.windows.Forms.CheckBox
$ChkStartPDVD.Text = "Start PowerDVD When mounting iso"
$ChkStartPDVD.AutoSize = $true
$ChkStartPDVD.Width = 95
$ChkStartPDVD.Height = 20
$ChkStartPDVD.location = new-object system.drawing.point(10,610)
$ChkStartPDVD.Font = "Microsoft Sans Serif,10"
$ChkStartPDVD.Checked = $true
$FrmMain.controls.Add($ChkStartPDVD)

#UpdateISOList
[void]$FrmMain.ShowDialog()
$FrmMain.Dispose()

#endregion

If you know better ways in Powershell to mount/unmount and get a list of virtual drives, please let me know. Always fun to make the code better!!
 

Copy files to flat file structure

Recently I needed to copy a bunch of files within a lot of subfolders, but I didn’t want the folders.
I just needed a flat file structure. Who needs folders anyway? 🙂

So, my solution is of course powershell.

CLS
$Source = "x:\sourcefolder"
$Destination = "y:\destinationfolder"
$Files = Get-ChildItem -LiteralPath $Source -Recurse -file -Force
[INT]$nr = '1'
ForEach($File in $Files){
    Write-Output "------------------------------------------------------------------------------------------"
    Write-Output "File $nr/$($Files.Count)"
    Write-Output "Copying file: $($File.name)"
    Write-Output "------------------------------------------------------------------------------------------"
    $File | Copy-Item -Destination $Destination
    $nr ++
}

Read and Write BIOS settings to Lenovo computers

Intro

 

As I often say, if you can automate things you have time to do more fun stuff.
And in windows deployment from SCCM/MDT i’ts always nice to even automate BIOS settings.

Lenovo have been smart in this way. Instead of using special tools, like HP and Dell, you can use WMI methods instead.

This might not be the best coding ever, but you might get the idea here….

Reading settings

The easiest way is probably to sett BIOS as you want it, boot up in Windows or Windows PE with powershell support in it and run this script.

ForEach($Obj in $BiosSettings){
    if ($Obj.CurrentSetting -ne "") {
        Write-Host $Obj.CurrentSetting.replace(",",";")
        $stream.WriteLine($Obj.CurrentSetting.replace(",",";"))
    }
}
$stream.close()

This will output all the BIOS settings in a textfile in the same directory as the script. You can easily change the values and/or remove values you don’t want to change.

Writing settings

$SettingsFile = "Settings.txt"
$SettingsObj = ""
$SettingsObj = Get-Content $PSScriptRoot\$SettingsFile
$BiosPass='mypassword'
$PasswordState = (gwmi -class Lenovo_BiosPasswordSettings -namespace root\wmi).PasswordState

function Set-LenovoBiosSettingsValues
{
    Param( [string]$WMIObj, [string]$WMIValue )

    If ($PasswordIsSet -eq $false) {
        (gwmi -class Lenovo_SetBiosSetting –namespace root\wmi).SetBiosSetting("$WMIObj,$WMIValue")
    }
    Else {
     (gwmi -class Lenovo_SetBiosSetting -namespace root\wmi).SetBiosSetting("$WMIObj,$WMIValue,$BiosPass,ascii,us")
    }

    gwmi -class Lenovo_BiosSetting -namespace root\wmi | Where-Object {$_.CurrentSetting.split(",",[StringSplitOptions]::RemoveEmptyEntries) -eq "$WMIObj"} |
    Format-List CurrentSetting
}

function Set-LenovoBiosSettings {

    #Check if BIOS password is set
    If ($PasswordState -eq '0') {
        $PasswordIsSet = $false
        Write-Host "BIOS password not set"
        }
    Else {
        $PasswordIsSet = $true
        Write-Host "BIOS password is set"
    }

    foreach ($setting in $SettingsObj) {
        $Sobj = ""
        $Svar1 = ""
        $Svar2 = ""
        $Sobj = $Setting -split ';'
        $Svar1,$Svar2=$Sobj

        Write-Host "Sets ""$Svar1"" to ""$Svar2"""
        Set-LenovoBiosSettingsValues -WMIObj $Svar1 -WMIValue $Svar2
    }
    #Saves the bios-settings
    Write-Host "Saving settings"
    (gwmi -class Lenovo_SaveBiosSettings -namespace root\wmi).SaveBiosSettings("$BiosPass,ascii,us")
}

# Start writing settings
Set-LenovoBiosSettings

There are some shortcomings with the way Lenovo has implemented this, some settings cannot be made.
For an example you cannot sett a BIOS password if there aren’t any allready. So you can only change password.
And you cannot set “PhysicalPresenceForTpmClear” to Disable. But only change from Disable to Enable.

Links

You you want to read more about this, you can read the offical documentation and maybe find other things you can do via the wmi.

https://support.lenovo.com/se/sv/solutions/ht100612