This fork contains the code to install GRUB2 directly on a LVM "physical volume" in a partitionless disk.
That means you would have no partitions and ONLY a PV on that disk in the 2nd, 3rd or 4th sector of the disk. The second sector is the default for a PV so we can say that this patch enables installation of Grub2 into a PV that was created normally with an additional flag (--bootloaderareasize 1M, as detailed below) but in its default location.
This fork has the code sitting in the pvinstall
branch of this repo. To checkout the code you must do:
git clone https://github.com/drydenp/grub2-pvinstall.git cd grub2-pvinstall git checkout pvinstall
to get at it. This branch contains all code. To see the diff against the 'master' branch you must do:
git diff upstream/master..pvinstall
after setting it up as detailed below.
* master: contains this readme * savannah: contains the upstream sources (not on GitHub) * pvinstall: contains the modifications (on GitHub)
You will find below instructions on how to actually set this up for development or maintenance. This master branch that you see now contains only documentation and possibly scripts. savannah
is going to be set to point to upstream/master
. The pvinstall
branch will contain the latest changes, notably rebased on top of "savannah" usually.
Normally "savannah" would be up to date with upstream master and contain no additional changes.
Upstream Grub2 just released GRUB 2.02rc2 (five days ago, 15-03-2017) and I haven't updated this repo in a while. Ideally it should be up to date with remote GRUB but I don't know if it applies cleanly at this point. Once GRUB 2.02 is released I will definitely try to find some time to at least get this up to date again and see if it cleanly applies, and make sure it does.
This (little) project is aimed at ensuring that Grub can detect and make use of a LVM2 "Physical Volume" in which space Grub2 core boot loader can be installed. A LVM2 "Physical Volume" typically reserves the boot loader area (first sector of 512 bytes) for a boot loader and installs itself (the Physical Volume header) in the 2nd sector and beyond. A Physical Volume created with
pvcreate <parameters> --bootloaderareasize 1M
is capable of having the GRUB2 core.img installed into it, that is to say that this extra space is needed for the installation of Grub.
The code below (I mean this repo) is intended to provide the necessary functionality for detecting and verifying and installing into this extra space.
This patch is still a work in progress (why else have this site) but I have not yet had enough time, patience, arduous labour, and help from the Grub2 team (most notably Andrei Borzenkov, who did help me get started) to finish it. This patch operates perfectly but requires a little more sanity checking.
There are three questions remaining:
- How to properly detect leftover "garbage" from a previous PV that _was_ suitable to prevent installation into a PV that _is not currently suitable_
- Whether installation into a PV that does not yet have any VGs should be allowed
- Whether we should allow installation without the -s flag (Andrei was against it).
It's been in use (by me) for quite some time, never had issues.
Additionally the util-linux
team updated libblkid
to allow detection of a PV even if the bootsector already contains a bootloader (as would be the case with our patch) in their version 2.29. This version is not yet included in Xenial (16.10) of Ubuntu, but it is included in the upcoming Zesty (17.04). This version is required for auto-activation of physical volumes using the udev
mechanism, which is the default for all SystemD systems.
Building is easy peasy and although there are dedicated packages you need most, I will just say that apt build-dep grub2
will install anything and everything on Ubuntu unless you care about hard disk space but then it will still do it. I thought most of that space requirement went in to the Qemu packages though. That's some 171MB of stuff you will not use.
It's just that Ubuntu (Debian) contains other stuff such as the update-grub script which you could just copy, and I'm sure you could build it using their package scripts.
Ubuntu's base version of Grub2 is at least as old as January, 2014. They backport patches from upstream whenever they feel like it. The last backported patch (and also the last patch they have) is from January 20 (2016).
My current patches apply cleanly to the Ubuntu base though.
To obtain a patch of my work, you can create a diff against the "savannah" branch (the way it is now).
git diff savannah pvinstall
But this will include any irrelevant house-keeping changes. Not that it matters.
A diff with only the most essential set of changes for the patch would have to be done against the last "housekeeping" commit from pvinstall. I just keep them in one branch although I could put the housekeeping changes in its own branch or just apply them to master. For now, I think this is cleaner.
git clone https://github.com/drydenp/grub2-pvinstall.git
should fetch this repo and set up the remote origin
cd grub2-pvinstall git remote add upstream git://git.savannah.gnu.org/grub.git git fetch upstream master git branch -t savannah upstream/master
will set up upstream and create a local branch savannah to track it. Savannah is not stored here on Github as a consequenc.
To have convenient access to the ubuntu branch you must do:
git symbolic-ref refs/heads/ubuntu refs/heads/pvinstall_ubuntu2.02beta2
git checkout savannah git pull
git checkout pvinstall git rebase savannah
The ubuntu branch is actually named in full "pvinstall_ubuntu2.02beta2" but as you have seen I have created a local symbolic reference called "ubuntu". This also gets updated by the below script that updates the Ubuntu source.
In order to update the Ubuntu branch with my commits:
git checkout ubuntu # I have tagged the "split-off" point "ubuntu_ignore" git reset --hard ubuntu_ignore # Remove any commits I have copied over from pvinstall previously git cherry-pick savannah..pvinstall # Copy commits from pvinstall onto the Ubuntu sources
An alternative way of finding the commit that changed the .gitignore file is:
git log --oneline .gitignore | head -1 | sed "s/ .*//"
You could do this by hand, but this works perfectly.
It does the following:
- fetch the latest grub2 source
- find its version number
- stash any changes in the working dir
- create a new branch for it
- empty the branch and remove all untracked files except ignored files
- move the Ubuntu sources to it
- add it with a commit message
- commit the ubuntu_ignore commit that will create a .gitignore file
- update the newly created commit to reference the tag
- move the temporary branch to a branch with the ubuntu version in it
- update the symbolic reference "ubuntu"
- remove remaining temporary files and the tmp directory
I do not maintain that branch that way though, so what you will see online or if you clone it will be the "bare" Ubuntu branch/repo.
ask_for_stash() { local answer echo "You have changes in your working directory. Aborting procedure" echo -e "\nExecute git stash -a to stash changes. Do you want me to do it for you?" read -ep "stash changes [y/n]: " answer if [ "$answer" = "y" ]; then echo "Saving current branch" oldbranch=$( git symbolic-ref HEAD --short ) && { echo "Stashing changes..." git stash -a } || { echo "Failed to stash. Need to abort now." false } fi }
revert_stash() { echo "Your old branch was stashed because the working directory was not clean." \ "Changing back to $oldbranch now and popping changes" git checkout $oldbranch && { git stash pop || echo "Popping failed, take care"; } || echo "Checking out failed, there should be changes in your stash" }
tmp=$( mktemp -d ) && { cd $tmp && apt source grub2 && { subdir=$( ls -d * --file-type | grep "/$" | sed 's@/$@@' ) && version=$( echo "$subdir" | sed "s/grub2-//" | tr -d '~' ) && cd - && [ -z "$( git status -s )" ] || ask_for_stash && git checkout --orphan pvinstall_ubuntu${version}_temp && { git rm -rf --ignore-unmatch . && git clean -df && mv $tmp/$subdir/* . && git add . && git commit -m "Ubuntu sources $version" && git cherry-pick ubuntu_ignore && git tag -af ubuntu_ignore -m "Tag pointing to most recent Ubuntu .gitignore commit" && { git branch -M pvinstall_ubuntu${version}_temp pvinstall_ubuntu${version} && { git symbolic-ref refs/heads/ubuntu refs/heads/pvinstall_ubuntu${version}; true; } } || git branch -D pvinstall_ubuntu${version}_temp [ $oldbranch ] && revert_stash } rm -rf $tmp/* } rmdir $tmp }
I just put that stashing code into its own functions for now. Without those functions it will just abort. I was actually meaning to reduce the mount of safety code, but instead I increased it :-/.