12

I have standard dual-boot system: Ubuntu and Windows. Grub is configured to launch Windows by default.

Is there a way to create some kind of link in Windows, that would:

  1. restart Windows
  2. boot into Ubuntu
3

4 Answers 4

10

You don't need to modify /boot/grub/grub.cfg like Michal Hagara suggested. This could break Ubuntu if you install a new kernel and doesn't update the e:\home\user\Grubshift\ubuntudefault\grub.cfg.

All you need to do is to create/copy a file /boot/grub/grubenv with following content

# GRUB Environment Block
next_entry=2
###########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################

Where next_entry is the line of the next grub menu entry which should be started next time (starting from zero). So next_entry=2 would be the 3th line.

Grub will automatically remove the value after boot so next time you'll boot into your default OS again.

This is how grub-reboot works.

3
  • This is much more convenient solution, thank you! Jun 12, 2015 at 0:25
  • Didn't know about that functionality :)... As you could see, I've pointed out, that messing with grub.cfg isn't the wisest... Jun 12, 2015 at 6:55
  • are you sure, that 987 times '#' is required? I think 462 times is sufficient :-D
    – Jounathaen
    Mar 13, 2020 at 11:02
2

Here is what I have in mind:

  • http://www.ext2fsd.com/ (it should be capable of writing to EXT partition, "mounting" and assigning letter on boot)
  • then I would prepare modified GRUB file, where Ubuntu is set as Default OS (this one would be stored on Linux partition too)
  • Windows BATCH script (executed by your desired shortcut) which would:
    1. Backup OLD GRUB (Windows as default)
    2. copy modified GRUB (default is Ubuntu) over OLD one (Default is Windows)
    3. Restart PC
  • Linux BASH script which would modify and update GRUB on startup (or reboot) to set back Windows as default OS

I can be completely wrong with this approach, but I can't see, why it shouldn't work.

EDIT:

And also there is: http://www.paragon-drivers.com/extfs-windows/ which I have never tried.


PROGRESS

1.Shortcut to restart Windows and boot Ubuntu

OK, down side of this is we will have to modify grub.cfg (/boot/grub/grub.cfg) directly (it is advised against - https://askubuntu.com/a/437341/402801),because there is no way to run update-grub from Windows... if you can live with that read further.

  • As I have mentioned before, install Ext2Fsd, make it auto-mount and assign letter on startup
  • I have created my "Backup folder" in /home/user/Grubshift with 3 sub directories: backup (for backing up actual /boot/grub/grub.cfg), ubuntudefault (for storing grub.cfg with Ubuntu as default), windowsdefault (you've got the idea)

After installation, Ubuntu is set as default, so copy that grub.cfg to your desired directory. I've got "Windows as default" config by modifying GRUB via grub-customizer (it's safer in my opinion), after that copy Windows grub.cfg to your desired directory

After that, open notepad and insert:

copy e:\boot\grub\grub.cfg /y e:\home\user\Grubshift\backup
copy e:\home\user\Grubshift\ubuntudefault\grub.cfg /y e:\boot\grub
shutdown /r /t 0

/y - option of copy command, suppresses prompting to confirm you want to overwrite an existing destination file

/r /t 0 - options of shutdown, 1. means reboot, 2. means immediately, without ugly messages popping up

Modify the path accordingly !!!

  • Save that file (I've used UTF-8) and change extension to *.bat
  • Create Desktop shortcut for shift.bat, right click on shorctur --> properties--> shortcut tab --> Run:minimized (that will get rid of CMD popping up)

I have tried this at least 8 times, setting Windows as default with grub-customizer ...

I'm not saying it's safe, but HEY!, we are messing with bootloader... that isn't safe

When it's fully working, we can get rid of GRUB menu completely, because it will always boot into right OS...

2
  • The logic looks good, sadly ext2fsd doesn't fully support ext4. Jun 11, 2015 at 17:33
  • 1
    Also if the script mucks up (as if Windows would ever do that :) the computer won't boot - good idea though. A good example is if the Linux script runs on boot, but the computer is shut down whilst booting and just executing that script, then....
    – Wilf
    Jun 11, 2015 at 19:06
1

Here's how I've set up my configuration:

To sum it up: System reboots default to last active, reboots from windows to linux and vice versa using a simple script.

Set up grub to always boot last selected:

Under linux:

  • enter GRUB_DEFAULT=saved and GRUB_SAVEDEFAULT=true in /etc/default/grub
  • update config using sudo update-grub

Install Paragons extfs driver

see http://www.paragon-drivers.com/extfs-windows/

Create reboot-scripts:

If /boot/grub/grubenv doesn't exist, create it using the answer from Germar

Batch-file for reboot from windows to linux:

@echo off
"C:\Program Files (x86)\Paragon Software\ExtFS for Windows\extmounter" /mount disk1 L:

:CheckForFile
IF EXIST "L:\boot\grub\grubenv" GOTO FoundIt
GOTO CheckForFile
:FoundIt

sed -i -e '/next_entry/c\next_entry=0' L:/boot/grub/grubenv
"C:\Program Files (x86)\Paragon Software\ExtFS for Windows\extmounter" /umount disk1 L:
echo press enter to reboot
pause
shutdown -r -t 00
  • replace /mount disk1 L: with something specific to your system. You can find available disks using the extmounter /list command and the drive letter. Also, L: must not be already taken.
  • save it as e.g. reboot-linux.bat
  • you can right-click on bat and select run as administrator to execute it

Shell script for reboot from linux to windows:

sudo sed -i -e '/next_entry/c\next_entry=2' /boot/grub/grubenv
sudo reboot
  • replace next_entry=2 with whatever your windows entry is.
  • save it as e.g. ~/reboot_windows and mark as executable: chmod +x ~/reboot_windows
1

I use Arch instead of Ubuntu but the GRUB configuration should be the same.

What I don't really like about the previous anwsers is that they:

  • either involve editing the grub.cfg file directly, which is intended for permanent changes
  • or edit the grubenv in a way that corrupts the GRUB environment block, which results in warnings on Linux boot and breaks the grub-editenv command

GRUB setup

So first of all you need to setup GRUB to remeber the last system booted to (it's convenient for reboots anyway):

  1. enter GRUB_DEFAULT=saved and GRUB_SAVEDEFAULT=true in /etc/default/grub
  2. update config using sudo update-grub (on Arch it's grub-mkconfig)

Linux side

There's this convenient command called grub-reboot which lets you one-shot boot into Windows. Very handy. Note that this keeps the last saved entry in GRUB, so when you go like Linux>grub-reboot to Windows>Windows>reboot it will reboot you back to Linux. To override this (unwanted IMO) behavior add another command afterward like this:

grub-reboot $name
grub-editenv /boot/grub/grubenv set saved_entry=$name

where $name is the name of Windows as it appears in GRUB. I explain it in detail below. After running these commands reboot the system.

Windows side

So I decided to investigate what the Linux script does. It calls grub-editenv and sets the value of next_entry to the desired OS. I spent a few hours doing trial and error editing the grubenv file trying to replicate the result and managed to come up with a solution. It turns out that the GRUB environment block should always be kept exactly 1024 bytes long, that's why there are # signs at the end by default. Here's my PowerShell script. It might be a bit verbose but it gets the job done correctly.

function Get-ArrLength {
    param (
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]$arr
    )

    $text = [string]::Join("`n", $arr)
    ($text | Measure-Object -Character).Characters
} 

mountvol P: /S
P:
cd grub
cp grubenv grubenv.bak
$name = "Arch Linux"
$name_len = ($name | Measure-Object -Character).Characters
$arr = cat grubenv
$original_length = Get-ArrLength $arr

$arr = $arr -replace "next_entry=","next_entry=$name"
foreach ($a in $arr) {
    if ($a -match "saved_entry=") {
        $arr[$arr.IndexOf($a)] = "saved_entry=$name"
    }
}

$candidate_length = Get-ArrLength $arr

if ($candidate_length -gt $original_length) {
    $arr[$arr.Count-1] = $arr[$arr.Count-1].SubString(0,$arr[$arr.Count-1].Length-($candidate_length-$original_length))
} elseif ($candidate_length -lt $original_length) {
    $arr[$arr.Count-1] = $arr[$arr.Count-1] + "#" * ($original_length-$candidate_length)
}

$contenttext = [string]::Join("`n", $arr)
sc grubenv ([byte[]][char[]] "$contenttext") -Encoding Byte
Restart-Computer
  • Replace the assignment of $name with the name of your installation as it appears in GRUB. If it's within a GRUB subfolder, use the > character as a path separator like so: $name="subfolder_name>OS_entry_name". Instead of names you can also use numbers where 0 is the first item as it appears in the GRUB menu but going with names is more versatile should the entries order change.
  • The letter P: in the lines mountvol P: /S and the following is completely arbitrary and you can change it to any drive letter that's available on your Windows system.
  • You can also remove the last command Restart-Computer if you only want to change the GRUB entries and later reboot manually.
  • The script creates a backup file called grubenv.bak so if anything goes wrong you can always restore it by simply copying it back to grubenv.
  • You should run the script as Administrator because it needs rights to write to the EFI partition.
  • The script might not work if your EFI partition's filesystem is not supported by Windows (mine is FAT32).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .