Showing posts with label freebsd. Show all posts
Showing posts with label freebsd. Show all posts

20201006

How to Recover From a BIOS Upgrade

Recovering From Firmware Upgrade

Recently, I booted Windows on my laptop for the first time in a while to play Portal 2 with my son. It asked me to upgrade, and I said 'sure, upgrade the BIOS.'

And then I couldn't boot FreeBSD...  The BIOS upgrade deleted all the BootXXXX variables. So it only booted Windows. I'm stuck, right? I have to download a FreeBSD image and boot off the USB drive. Or did I?

Note: Even the update program called updating the firmware updating the BIOS. BIOS is the generic term for the bit of code that runs before the OS. Sadly, it's also the term people use to describe the pre-UEFI boot environment on PCs, so it can be a confusing term to use. Firmware seems a bit better, but it's also ambiguous because different bits of hardware (like wireless cards) also need firmware loaded.

How to Recover

I was in windows. I needed to mount the system partition (EFI). So, I opened the Administrative Console and got a command prompt from there on the 'Tools' tab. This lead to the familiar C: prompt.  I have no W drive. There I was able to copy FreeBSD's boot loader like so:

C:\WINDOWS\system32> mountvol w: /s
C:\WINDOWS\system32>w:
W:\> cd EFI\Microsoft\Boot
W:\EFI\Microsoft\Boot> ren bootmgfw.efi bootmgfw-back.efi
W:\EFI\Microsoft\Boot> copy W:\EFI\FreeBSD\loader.efi bootmgfw.efi
W:\EFI\Micorsoft\Boot> 

I then rebooted from the menu.

I had remembered from my efibootmgr hacking that the boot loader was here. After I booted to FreeBSD, I was able to confirm:

% sudo efibootmgr -v
Boot to FW : false
BootCurrent: 0001
Timeout    : 0 seconds
BootOrder  : 0001, 2001, 2002, 2003
+Boot0001* Windows Boot Manager HD(1,GPT,f859c46d-19ee-4e40-8975-3ad1ab00ac09,0x800,0x82000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
                                   nvd0p1:/EFI/Microsoft/Boot/bootmgfw.efi /boot/efi//EFI/Microsoft/Boot/bootmgfw.efi
 Boot2001* EFI USB Device 
 Boot2002* EFI DVD/CDROM 
 Boot2003* EFI Network 


Unreferenced Variables:

I was then able to add FreeBSD back with efibootmgr. I mount the ESP on /boot/efi:

sudo efibootmgr --create --loader /boot/efi/EFI/freebsd/loader.efi --kernel /boot/kernel/kernel --activate --verbose --label FreeBSD
Boot to FW : false
BootCurrent: 0001
Timeout    : 0 seconds
BootOrder  : 0000, 0001, 2001, 2002, 2003
 Boot0000* FreeBSD HD(1,GPT,f859c46d-19ee-4e40-8975-3ad1ab00ac09,0x800,0x82000)/File(\EFI\freebsd\loader.efi)
               nvd0p1:/EFI/freebsd/loader.efi /boot/efi//EFI/freebsd/loader.efi
           HD(6,GPT,68f0614d-c322-11e9-857a-b1710dd81c0d,0x7bf1000,0x1577e000)/File(boot\kernel\kernel)
               nvd0p6:boot/kernel/kernel /boot/kernel/kernel
+Boot0001* Windows Boot Manager HD(1,GPT,f859c46d-19ee-4e40-8975-3ad1ab00ac09,0x800,0x82000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
                                   nvd0p1:/EFI/Microsoft/Boot/bootmgfw.efi /boot/efi//EFI/Microsoft/Boot/bootmgfw.efi
 Boot2001* EFI USB Device 
 Boot2002* EFI DVD/CDROM 
 Boot2003* EFI Network 


Unreferenced Variables:
%

Once this is in place, I needed to undo what I'd done to Windows:

% cd /boot/efi/EFI/Microsoft/Boot
% sudo mv bootmgfw-back.efi bootmgfw.efi

I was then able to reboot to FreeBSD. And fun fact: since the boot order is 0000, 0001, that means I can boot to Windows by just typing 'quit' at the loader prompt. This causes the boot loader to exit with an error, which causes the BIOS to try the next BootXXXX variable, in this case windows.

And there it is: I was able to recover my system without downloading a USB image...


20201001

FreeBSD Subversion to Git Migration: Pt 2 Primer for Users

FreeBSD git Primer for Users

Today's blog is actually a preview of a git primer I'm writing for the FreeBSD project. It covers what a typical user will need, including those relatively rare users that may have some changes to the base. Please let me know what you think, and ways it can be improved. I'm keen on especially clear and useful pointers for the topics as well.

Also note: The cgit-beta mirror mentioned below is currently for testing purposes only.

If you have a lot of suggests, you can make them directly on the original for this on hackmd.

Scope

If you want to download FreeBSD, compile it from sources and generally keep up to date that way, this primer is for you. If you are looking to do more with the tree, contribute back, or commit changes, then you will need to wait for a later blog where I cover that. It covers getting the sources, updating the sources, how to bisect and touches briefly on how to cope with a few local changes. It covers the basics, and tries to give good pointers to more in-depth treatment for when the readers finds the basics insufficient.

Keeping Current With FreeBSD src tree

First step: cloning a tree. This downloads the entire tree. There’s two ways to download. Most people will want to do a deep clone of the repo. However, there are times that you may wish to do a shallow clone.

Branch names

The branch names in the new git repo are similar to the old names. For the stable branches, they are stable/X where X is the major release (like 11 or 12). The main branch in the new repo is ‘main’. The main branch in the old github mirror is ‘master’. Both reflecting the defaults of git at the time they were created. The main/master branch is the default branch if you omit the ‘-b branch’ or ‘–branch branch’ options below.

Repositories

At the moment, there’s two repositories. The hashes are different between them. The old github repo is similar to the new cgit repo. However, there are a large number of mistakes in the github repo that required us to regenerate the export when we migrated to having a git repo be the source of truth for the project.

The github repo is at https://github.com/freebsd/freebsd.git
The new cgit beta repo is at https://cgit-beta.freebsd.org/src.git
These will be $URL in the commands below.

Note: The project doesn’t use submodules as they are a poor fit for our workflows and development model. How we track changes in third-party applications is discussed elsewhere and generally of little concern to the casual user.

Deep Clone

A deep clone pulls in the entire tree, as well as all the history and branches. It’s the easiest to do. It also allows you to use git’s worktree feature to have all your active branches checked out into separate directories but with only one copy of the repository.

git clone $URL -b branch [dir]

is how you make a deep clone. ‘branch’ should be one of the branches listed in the previous section. It is optional if it is the main/master branch. dir is an optional directory to place it in (the default will be the name of the repo you are clone (freebsd or src)).

You’ll want a deep clone if you are interested in the history, plan on making local changes, or plan on working on more than one branch. It’s the easiest to keep up to date as well. If you are interested in the history, but are working with only one branch and are short on space, you can also use --single-branch to only download the one branch (though some merge commits will not reference the merged-from branch which may be important for some users who are interested in detailed versions of history).

Shallow Clone

A shallow clone copies just the most current code, but none or little of the history. This can be useful when you need to build a specific revision of FreeBSD, or when you are just starting out and plan to track the tree more fully. You can also use it to limit history to only so many revisions.

git clone -b branch --depth 1 $URL [dir]

This clones the repository, but only has the most recent version in the respository. The rest of the history is not downloaded. Should you change your mind later, you can do ‘git fetch --unshallow’ to get the old history.

Building

Once you’ve downloaded, building is done as described in the handbook, eg:

% cd src
% make buildworld
% make buildkernel
% make installkernel
% make installworld

so that won’t be coverd in depth here.

Updating

To update both types of trees uses the same commands. This pulls in all the revisions since your last update.

git pull --ff-only

will update the tree. In git, a ‘fast forward’ merge is one that only needs to set a new branch pointer and doesn’t need to re-create the commits. By always doing a ‘fast forward’ merge/pull, you’ll ensure that you have an identical copy of the FreeBSD tree. This will be important if you want to maintain local patches.

See below for how to manage local changes. The simplest is to use --autostash on the ‘git pull’ command, but more sophisticated options are available.

Selecting a Specific Version

In git, the ‘git checkout’ command can not only checkout branches, but it can also checkout a specific version. Git’s versions are the long hashes rather than a sequential number. You saw them above in the conflict when it said it couldn’t apply “646e0f9cda11”.

When you checkout a specific version, just specify the hash you want on the command line (the git log command can help you decide which hash you might want):

git checkout 08b8197a74

and you have that checked out.

However, as with many things git, it’s not so simple. You’ll be greeted with a message similar to the following:

Note: checking out '08b8197a742a96964d2924391bf9fdfeb788865d'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 08b8197a742a hook gpiokeys.4 to the build

where the last line is generated from the hash you are checking out and the first line of the commit message from that revision. Also, a word about hashes: they can be abbreviated. That’s why you’ll see them have different lengths in different commands or their outputs. These super long hashes are often unique after 6 or 10 characters, so git lets you abbreviate and is somewhat inconsistent about how it presents them to users.

Bisecting

Sometimes, things go wrong. The last version worked, but the one you just updated to does not. A developer may ask to bisect the problem to track down which commit caused the regression.

If you’ve read the last section, you may be thinking to yourself “How the heck do I bisect with crazy version numbers like that?” then this section is for you. It’s also for you if you didn’t think that, but also want to bisect.

Fortunately, one uses the ‘git bisect’ command. Here’s a brief outline in how to use it. For more information, I’d suggest https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-elimination or https://git-scm.com/docs/git-bisect for more details. The man page is good at describing what can go wrong, what to do when versions won’t build, when you want to use terms other than ‘good’ and ‘bad’, etc, none of which will be covered here.

‘git bisect start’ will start the bisection process. Next, you need to tell a range to go through. ‘git bisect good XXXXXX’ will tell it the working version and ‘git bisect bad XXXXX’ will tell it the bad version. The bad version will almost always be HEAD (a special tag for what you have checked out). The good version will be the last one you checked out.

A quick aside: if you want to know the last version you checked out, you should use ‘git reflog’:

5ef0bd68b515 (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: pull --ff-only: Fast-forward
a8163e165c5b (upstream/master) HEAD@{1}: checkout: moving from b6fb97efb682994f59b21fe4efb3fcfc0e5b9eeb to master
...

shows me moving the working tree to the master branch (a816…) and then updating from upstream (to 5ef0…). In this case, bad would be HEAD (or 5rf0bd68) and good would be a8163e165. As you can see from the output, HEAD@{1} also often works, but isn’t foolproof if you’ve done other things to your git tree after updating, but before you discover the need to bisect.

Back to git bisect. Set the ‘good’ version first, then set the bad (though the order doesn’t matter). When you set the bad version, it will give you some statistics on the process:

% git bisect start
% git bisect good a8163e165c5b
% git bisect bad HEAD
Bisecting: 1722 revisions left to test after this (roughly 11 steps)
[c427b3158fd8225f6afc09e7e6f62326f9e4de7e] Fixup r361997 by balancing parens.  Duh.

You’d then build/install that version. If it’s good you’d type ‘git bisect good’ otherwise ‘git bisect bad’. You’ll get a similar message to the above each step. When you are done, report the bad version to the developer (or fix the bug yourself and send a patch). ‘git bisect reset’ will end the process and return you back to where you started (usually tip of main). Again, the git-bisect manual (linked above) is a good resource for when things go wrong or for unusual cases.

Ports Considerations

The ports tree operates the same way. The branch names are different and the repos are in different locations.

The github mirror is at https://github.com/freebsd/freebsd-ports.git
The cgit mirror is https://cgit-beta.freebsd.org/src.git

As with ports, the ‘current’ branches are ‘master’ and ‘main’ respectively. The quarterly branches are named the same as in FreeBSD’s svn repo.

Coping with Local Changes

Here’s a small collections of topics that are more advanced for the user tracking FreeBSD. If you have no local changes, you can stop reading now (it’s the last section and OK to skip).

One item that’s important for all of them: all changes are local until pushed. Unlike svn, git uses a distributed model. For users, for most things, there’s very little difference. However, if you have local changes, you can use the same tool to manage them as you use to pull in changes from FreeBSD. All changes that you’ve not pushed are local and can easily be modified (git rebase, discussed below does this).

Keeping local changes

The simplest way to keep local changes (especially trivial ones) is to use ‘git stash’. In its simples form, you use ‘git stash’ to record the changes (which pushes them onto the stash stack). Most people use this to save changes before updating the tree as described above. They then use ‘git stash apply’ to re-apply them to the tree. The stash is a stack of changes that can be examined with ‘git stash list’. The git-stash man page (https://git-scm.com/docs/git-stash) has all the details.

This method is suitable when you have tiny tweaks to the tree. When you have anything non trivial, you’ll likely be better off keeping a local branch and rebasing. It is also integreated with the ‘git pull’ command: just add ‘–autostash’ to the command line.

Keeping a local branch

It’s much easier to keep a local branch with git than subversion. In subversion you need to merge the commit, and resolve the conflicts. This is managable, but can lead to a convoluted history that’s hard to upstream should that ever be necessary, or hard to replicate if you need to do so. Git also allows one to merge, along with the same problems. That’s one way to mange the branch, but it’s the least flexible.

Git has a concept of ‘rebasing’ which you can use to avoids these issues. The ‘git rebase’ command will basically replay all the commits relative to the parent branch at a newer location on that parent branch. This section will briefly cover how to do this, but will not cover all scenarios.

Create a branch

Let’s say you want to make a hack to FreeBSD’s ls command to never, ever do color. There’s many reasons to do this, but this example will use that as a baseline. The FreeBSD ls command changes from time to time, and you’ll need to cope with those changes. Fortunately, with git rebase it usually is automatic.

% cd src
% git checkout main
% git checkout -b no-color-ls
% cd bin/ls
% vi ls.c     # hack the changes in
% git diff    # check the changes
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index 7378268867ef..cfc3f4342531 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#undef COLORLS
 #ifdef COLORLS
 #include <termcap.h>
 #include <signal.h>
% # these look good, make the commit...
% git commit ls.c

The commit will pop you into an editor to describe what you’ve done. Once you enter that, you have your own local branch in the git repo. Build and install it like you normally would, following the directions in the handbook. git differs from other version control systems in that you have to tell it explicitly which files to use. I’ve opted to do it on the commit command line, but you can also do it with ‘git add’ which many of the more in depth tutorials cover.

Time to update

When it’s time to bring in a new version, it’s almost the same as w/o the branches. You would update like you would above, but there’s one extra command before you update, and one after. The following assumes you are starting with an unmodified tree. It’s important to start rebasing operations with a clean tree (git usually requires this).

% git checkout main
% git pull --no-ff
% git rebase -i main no-color-ls

This will bring up an editor that lists all the commits in it. For this example, don’t change it at all. This is typically what you are doing while updating the baseline (though you also use the git rebase command to curate the commits you have in the branch).

Once you’re done with the above, you’ve move the commits to ls.c forward from the old version of FreeBSD to the newer one.

Sometimes there’s merge conflicts. That’s OK. Don’t panic. You’d handle them the same as you would any other merge conflicts. To keep it simple, I’ll just describe a common issue you might see. A pointer to a more complete treatment can be found at the end of this section.

Let’s say the includes changes upstream in a radical shift to terminfo as well as a name change for the option. When you updated, you might see something like this:

Auto-merging bin/ls/ls.c
CONFLICT (content): Merge conflict in bin/ls/ls.c
error: could not apply 646e0f9cda11... no color ls
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 646e0f9cda11... no color ls

which looks scary. If you bring up an editor, you’ll see it’s a typical 3-way merge conflict resolution that you may be familiar with from other source code systems (the rest of ls.c has been omitted):

<<<<<<< HEAD
#ifdef COLORLS_NEW
#include <terminfo.h>
=======
#undef COLORLS
#ifdef COLORLS
#include <termcap.h>
>>>>>>> 646e0f9cda11... no color ls

The new code is first, and your code is second. The right fix here is to just add a #undef COLORLS_NEW before #ifdef and then delete the old changes:

#undef COLORLS_NEW
#ifdef COLORLS_NEW
#include <terminfo.h>

save the file. The rebase was interrupted, so you have to complete it:

% git add ls.c
% git rebase --cont

which tells git that ls.c has changed and to continue the rebase operation. Since there was a conflict, you’ll get kicked into the editor to maybe update the commit message.

If you get stuck during the rebase, don’t panic. git rebase --abort will take you back to a clean slate. It’s important, though, to start with an unmodified tree.

For more on this topic, https://www.freecodecamp.org/news/the-ultimate-guide-to-git-merge-and-git-rebase/ provides a rather extensive treatment. It goes into a lot of cases I didn’t cover here for simplicity that are useful to know since they come up from time to time.

Updating to a New FreeBSD Branch

Let’s say you want to main the jump from FreeBSD stable/12 to FreeBSD current. That’s easy to do as well, if you have a deep clone.

% git checkout main
% # build and install here...

and you are done. If you have a local branch, though, there’s one or two caveats. First, rebase will rewrite history, so you’ll likely want to do something to save it. Second, jumping branches tends to encounter more conflicts. If we pretend the example above was relative to stable/12, then to move to main, I’d suggest the following:

% git checkout no-color-ls
% git checkout -b no-color-ls-stable-12   # create another name for this branch
% git rebase -i stable/12 no-color-ls --onto main

What the above does is checkout no-color-ls. Then create a new name for it (no-color-ls-stable-12) in case you need to get back to it. Then you rebase onto the main branch. This will find all the commits to the current no-color-ls branch (back to where it meets up with the stable/12 branch) and then it will replay them onto the main branch creating a new no-color-ls branch there (which is why I had you create a place holder name).

20200919

FreeBSD Subversion to Git Migration: Pt 1 Why?

 FreeBSD moving to Git: Why

With luck, I'll be writing a few blogs on FreeBSD's move to git later this year. Today, we'll start with "why"?

Why?

There's a number of factors motivating the change. We'll explore the reasons, from long term viability of Subversion, to wider support for tools that will make the project better. Today I'll enumerate these points. There are some logistical points around how the decision was made. I'll not get into the politics about how we got here, though. While interesting for insiders who like to argue and quibble, they are no more relevant to the larger community that the color of the delivery truck that delivered groceries to your grocer this morning (even if it had the latest episode of a cool, scrappy cartoon cat that was involved in a multi-year arc wooing the love of his life by buying food at this store).

Apache has moved on, so has llvm

The Apache Foundation used to be the care taker and main user for Subversion. They used Subversion for all their repos. While they still technically the caretaker of Subversion, they've moved all their repositories to git. This is a worrying development because the foreseeable outcome of this will be less Subversion development. This will mean the FreeBSD project will need to undertake to support Subversion if we remain on it in the long term. FreeBSD is now the last, large Open Source project using Subversion. LLVM has made its transition to git recently. There are very real concerns about the health and viability of the Subversion ecosystem, especially when compared to the thriving, vibrant git ecosystem.

Better CI support

Git have more support for newer CI tools than subversion. This will allow us, once things are fully phased in, to increase the quality of the code going into the tree, as well as greatly reduce build breakages and accidental regressions. While one can use CI tools outside of git, integration into a git workflow requires less discipline on the part of developers, making it easy for them to fix issues found by CI as part of the commit/merge process before they affect others.

Better Merging

Git merging facilities are much better than subversion. You can more easily curate patches as well since git supports a rebase workflow. This allows cleaner patches that are logical bits for larger submissions. Subversion can't do this.

Git also allows integration of multiple git repositories with subtree rewriting via 'git subtree merge'. This allows for easier tracking of upstream projects and will allow us to improve the vendor import work flow.

Robust Mirroring

Git can easily and robustly be mirrored. Subversion can be mirrored, but that mirroring is far from robust. One of the snags in the git migration is that different svn mirrors have different data than the main repo or each other. Mirroring in git is built into the work flow. Since every repo is cloned, mirroring comes along for free. And there's a number of third party mirroring sites available, such as GitHub, GitLab and SourceForge. These sites offer collaboration and CI add ons as well.

Git can sign tags and commits. Subversion cannot. We can increase the integrity of the source of truth though these measures.

Features from 3rd Party Sites

Mirroring also opens up more 3rd party plug ins. Gitlab can do some things, Github other things, in terms of automated testing and continuous integration. Tests can be run when branches are pushed. Both these platforms have significant collaboration tools as well, which will support groups going off and creating new features for FreeBSD.  While one can use these things to a limited degree, with subversion mirrored to GitHub, the full power of these tools isn't fully realized without a conversion to git.

The wide range of tools available on these sites, or in stand-alone configurations, will allow us to have both pre-commit checks, as well as long-term post-commit tests running on a number of different platforms. This will allow the project to leverage existing infrastructure where it makes financial sense to let others run the tests, while still allowing the project to retain control of the bits that are critical to our operations.

Improved User-Submitted Patch Tracking and Integration

One area we've struggled with as a project is patch integration. We have no clear way to submit patches that will be acted on in a timely fashion, or at least that's the criticism. We do have ways, but they are only partially effective at integrating patches into the tree. Pull requests, of various flavors, offer a centralized way to accept patches, and have tools to review them. This should lower the friction to people submitting patches, as well as making it easier for developers to review the patches. Other projects have reported increased patch flow when moving to git. This can also be coupled with automated testing and other validation of the patch before the developer looks at it, which addresses one of the big issues with past systems: very low signal to noise ratio. While not a panacea, it will make things better and more widely use the scarce developer time.

Collaboration

Some have said that git, strictly speaking, isn't a pure source code management system. It is really a collaboration tool that also supports versioning. This may sound like a knock on git, but really it's git's greatest strength. Git's distributed model allows for easier and more frequent collaboration. Whole webs sites have been built around this concept, and show the power of easy collaboration to amplify efforts and build community.

Skill Set

All of this is before the skill set arguments are made about kids today just knowing git, but needing to learn subversion. That has had increasing been a source of friction. This argument is supported both by anecdotal evidence of people complaining about having to learn Subversion, about professors having to take time to teach it, etc. In addition, studies in the industry have shown a migration to git away from other alternatives. Git now has between 80% and 90% of the market, depending on which data you look at. It's so widely used that our non-use of it is a source of friction for new developers.

Developers are already moving

More and more of the active developers on the project use git for all or part of their development efforts. This has lead to a minor amount of friction because all these ways are not standardized, have fit and finish issues when pushing the changes into subversion, and cause friction. The friction is somewhat offset by the increase in productivity they offer these developers. The thinking is that having git as source of truth will unlock the potential of git even more to increase productivity.

Downsides

First, git has no keyword expansion support for implementing $FreeBSD$. While one can quibble over the git add-ins that do this sort of thing, the information added isn't nearly as useful as Subversions'. This will represent a loss. However, tagged keyword expansion has been going out of style for a long time. It used to be that source code control systems would embed the commit history in files committed, only to discover weird things happened when they were imported into other projects so the practice withered. We ran into a similar issue years ago with $Id$ and all the projects switched to $FooBSD$ instead. This was useful when source code tracking was weak and companies randomly imported versions: it told us what versions were there. Now, companies tend to do this with git, which has better tracking to the source abilities. The value isn't zero, but it's much lower than when we adopted it in the 90s. Git also doesn't support dealing with all the merge conflicts it causes very well. Since the tool rewards people for importing in a more proper way, more companies appear to be using it that way, lessening the need for explicit source marking. [edit: some don't consider this a loss at all].

Second, git doesn't have a running count of commits. One can work around this in a number of ways, but there's nothing fundamental that can be used as a commit number as reliably as subversion. Even so, the workarounds suffice for most uses, and many projects are using git and commit counts successfully today.

Third, the BSDL git clients are much less mature than the GPL ones. Until recently, there was no C client that could be imported into the tree. While one might debate whether or not that's a good idea, there's a strong cultural heritage of having all you need in the base system that's hard to shrug off. OpenBSD recently wrote got which has an agreeable license (but a completely different command line interface, for good or ill). It has its issues, which aren't relevant here, but is maturing nicely. Even with the current restrictions, it is usable. There is an active port of got to FreeBSD due to the large number of OpenBSDisms that are baked in (some necessary, some gratuitous). The OpenBSD people are open to having a portable version of got, so this is encouraging.

Finally, Change Is HARD. It's easy to keep using the same tools, with the same work flows with with the same people as you did yesterday. Learning a new system is difficult. Migrating one work flow to another is tricky. You have to balance the accumulated knowledge and tooling benefits vs the cost it will take to move to something new. The git migration team views moving from subversion to git as the first step in many of improving and refining FreeBSD's work flow. As such, we've tried to create a git workflow that will be familiar to old users and developers, and at the same time allow for further innovation in the future.

Conclusion

Although it's not without risk and engineering trade offs, the bulk of the evidence strongly suggests that moving to git will increase our productivity, improve project participation, grow the community, increase quality and produce a better system in the end. It will give us a platform that we can also re-engineer other aspects of the project. This will come at the cost of retooling our release process, our source distribution infrastructure and developers needing to learn new tools. The cost will be worth it, as it will pay dividends for years to come.

20200627

Whither chroot?

Chroot Origins

This blog post will examine original artifacts to clear up some confusion about where chroot(2) and chroot(8) came from. The answer turns out to be simple, and the confusion was understandable. This shows the benefits of groups like TUHS in preserving Unix history, and how the kindness of Caldera and Lucent in releasing the historic Unix systems has helped in our understanding of the evolution of Unix. 

EDIT: After initially published, this was revised with more links to historic artifacts (inline and in the Appendix) and a screen shot of wikipedia. The Wikipedia chroot entry has since been updated.

tl;dr: chroot(2) came from 7th Edition Unix

chroot is system call 61 in 7th Edition Unix from Bell Labs. There is no chroot system call in 6th Edition or earlier. All derivatives of 7th edition have chroot(2) for at least 2 decades after the 7th Edition release in 1979.

What confusion?

Wikipedia has this in their entry for chroot:
which suggests that Bill Joy had something to do with its creation in the BSD world. Turns out it's confused because earlier literature on the topic is also confused.

What Sparked the Confusion?

Poul-Henning Kamp created the jail system for FreeBSD. This system takes a chroot environment to the next level in terms of security. As a security device, chroot was terrible because it's fairly easy to jailbreak out of a chroot if you are root. The short version is to open '/' to get a reference to it. Then chroot to some directory further down the tree. Then fchdir to the fd you saved from '/'. Now chdir(".."); a bunch of times. This will walk you back to the real root. Now chroot(".") and you are out. There's lots of variations on this theme, and dozens of papers in the literature and an almost infinite number of ways to leak references to FDs outside the jail...

One of the wonderful thing he did was to create an extensive set of docs and write a paper about the jail(2) facilities. In this paper Mr Kamp wrote:
[CHROOT]
Dr. Marshall Kirk Mckusick, private communication: ``According to the SCCS logs, the chroot call was added by Bill Joy on March 18, 1982 approximately 1.5 years before 4.2BSD was released. That was well before we had ftp servers of any sort (ftp did not show up in the source tree until January 1983). My best guess as to its purpose was to allow Bill to chroot into the /4.2BSD build directory and build a system using only the files, include files, etc contained in that tree. That was the only use of chroot that I remember from the early days.''
This paper was presented at the 2nd International System Administration and Networking Conference "SANE 2000" May 22-25, 2000 in Maastricht, The Netherlands and is published in the proceedings.

In 2000, the BSD SCCS tree was not publicly available. Dr McKusick had access to it as his role with the Computer Science Research Group (CSRG) that produce the 4BSD releases. This predated various litigation that suggested 32V had no copyright, and the Ancient Unix License that SCO granted for 32V, so it was necessarily private per agreements between AT&T and The University of California at Berkeley.

What Actually Happened in 1982?

What happened was a shuffling of the deck chairs. the commit log, made as root, from March 18, 1992 says:

rearrange for kirk

SCCS-vsn: 4.21
and introduces chroot to ufs_syscalls.c. If you read the diffs, it also introduced 'open', 'creat' and several others to this file. These system calls are known to be in the PDP-7 Unix implementation, so it's unlikely that they were really introduced in this commit. One problem that makes this harder to track is that SCCS didn't track renames, and ufs_syscalls.c was renamed to vfs_syscalls.c in 4.4BSD.  It's quite clearly in ufs_syscalls.c in 4.1cBSD:
/*
 * Change notion of root (``/'') directory.
 */
chroot()
{

        if (suser())
                chdirec(&u.u_rdir);
}
which is the identical code that was added by Bill Joy to ufs_syscalls.c. This was moved between 4.1BSD and 4.1c from sys4.c as part of the UFS work, and is different only by the BSD-stylistic change to add a blank line before the rest of the code if there's no local variables:
chroot()
{
        if (suser())
                chdirec(&u.u_rdir);
}
which, apart from the comment, is identical. Without beating a dead horse (too late?), this code is the same all the way back to 4BSD, 3BSD, 32V, 2.8BSD and finally to V7:
chroot()
{
        if (suser())
                chdirec(&u.u_rdir);
}
Since the code is identical from V7 all the way through 4.2BSD when it was, according to this footnote in the jail appeared, added. This is direct evidence that the footnote was in error.

So what was the rearrangement for Kirk? It was to move things around in the kernel to make the system calls more generic. It was code motion, nothing more, that Dr. McKusick was reporting in the private email to Mr Kamp. Now that the SCCS tree is public, via a translation to svn by John Baldwin, we can see the above.

chroot(2) Conclusions

Given that the code was moved around alot, it's an understandable mistake that Dr. McKusick made, which explains how the error could have happened. Given that the code is identical to v7 code, and it was somewhere in all the extant versions between the two (2BSD, 32V, 3BSD, 4.0BSD, 4.1BSD, 4.1cBSD and 4.2BSD), modulo a trivial whitespace change, we can conclude that Bill Joy did not introduce chroot into 4.2BSD, but instead it was moved around a lot from the original V7 code.

The FreeBSD chroot(2) manual has been updated to correct this mistake.

But what about chroot(8)?

But what about chroot(8)? There's some confusion about this as well. Until recently, chroot(8) said in FreeBSD:
HISTORY
     The chroot utility first appeared in 4.4BSD.
However, that too is in error (or was at least not precise enough). The error comes from the 4.4BSD release itself, which has identical text. In a sense this is not wrong. 4.4BSD was the first full release that chroot(8) appeared in in the Berkeley world. It's first appearance, though, in any BSD tape was in the interim 4.3BSD-Reno release.

But what about the AT&T world? There, more system calls are wrapped in programs to make it easier to use in shell scripts. It turns out that System III had a usr/src/cmd/chroot.c, which I won't quote here, that's a different chroot than appeared in BSD (the code looks completely different, apart from the elements that have to be the same...). So, the history has been corrected to read:
HISTORY
     The chroot utility first appeared in AT&T System III UNIX and
     4.3BSD-Reno.
to represent the first time in each of the two branches of Unix after the 7th Edition that it appeared.

And that concludes today's software archeology deep dive on chroot...

Appendix

Here's the evolution of the chroot(2) implementation, as see from TUHS. You'll need to search for 'chroot()' in each of these source files since the current TUHS web site doesn't allow line number links.
AT&T Unix: V7, 32V, System III, System V

I'd also like to plug the Historic Unix Repo, which also helps navigate and allows line numbers. Here's a link to the 4.1c version, for example. I recalled this after I'd found all the TUHS references, or I'd done all of them like that.

20170411

Installing FreeBSD-current with 11.0R installation image

Just a quick blog to document a trick.

Boot the install image (or even just a boot-only image). Get a Shell. At the shell, type
# env UNAME_r=12.0-CURRENT bsdinstall auto
and it will get the latest 12.0-current build installed. Thanks to Allan Jude for alerting me of this trick.

20170405

Compiling sdcc for FreeBSD

In preparation for a possible new project, I needed to build sdcc, a compiler that targets a bunch of 8-bit architectures. You can find information about sdcc at their sourceforge page: http://sdcc.sourceforge.net/

Usually, this is just a port away. But due to looking at the wrong tree, I thought I had to compile it myself. The port and package are great, and are what people should normally be using, but the problems showed the need to use a trick or three to get the job done. I thought I'd document them here, since they are minimal and easy to write up.

FreeBSD's compiler doesn't default to having /usr/local/include in its include path, or /usr/local/lib in its library path. Normally, one would try to get around this by just add --prefix /usr/local to the configure command. However, that doesn't work for the sdcc stuff (since it is already the default). You have to explicitly add more things to the command line. After some digging, it turns out it's only a few variables to worry about:


./configure CC=clang CXX=clang++ CPPFLAGS="-I/usr/local/include -L/usr/local/lib" CFLAGS="-I/usr/local/include -L/usr/local/lib"
 The key ones here are CPPFLAGS and CFLAGS.

With that, I have a build sdcc. But it's a pain to install. The port / package is much easier for that reason alone.

20160109

Details on coming automatic module loading in FreeBSD

Automatic Module Loading

For a long time, I've wanted to add better, automatic module loading to FreeBSD. This past year, I started implementing that feature. Time and work pressures prevented me from completing it.

Some background

Every device that we have in our systems is enumerated in one of two ways. Either the bus gives us a list of all the devices, with certain per-device attributes (called plug and play data), or the device is attached through some other means. These latter devices are beyond the scope of this work, and there's generally very few of them in the system, and they aren't optional. The other devices, sometimes called 'self-enumerating' devices, have enough plug and play data for drivers in the system to decide if that driver can drive them or not. Most operating systems assign devices to drivers using this data. Some have the data encoded into tables in the filesystem (Windows, OS  X and Solaris), while others encode the data into the drivers (FreeBSD, NetBSD, OpenBSD, Linux, Dragon Fly BSD), though Linux offers some hybridization when it comes to certain devices. Except for FreeBSD, all these other OSes are beyond the scope of this work. And there's certainly room for debate over which approach is best, but we'll leave that behind as well.

Some busses on FreeBSD, like USB and PC Card, have very stylized probe routines. Drivers for devices on these busses generally call some bus-provided routine to match the device against a table that's basically the same for all drivers (though there's usually some stylized way to attach extra data). These drivers are easy to adapt to this new scheme because while some custom code needs to be written for each bus, each driver of that bus can generally use a macro to implement marking the PNP data (more on what marking means in a bit).

Other busses, like PCI, leave it entirely to the driver. So most of the drivers in the system have written their own matching routines that essentially loop through a table matching some attribute the bus provides to decide if the device is for them. These busses are harder to adapt.

But either way, most all drivers have some table of plug and play data that they use to filter their choice of devices. Since drivers are compiled into modules, this means most modules on the system have this data too. However, given the chaotic nature of the different busses, it's impossible for a program to find this data, unless it has very specific knowledge of each and every driver on the system (though for some classes of drivers, like USB and PC Card, it needn't know everything).

Finally, switching gears a bit, we have modules. Modules in the system record dependencies on other modules in the system using special macros. When the modules are installed, kldxref(8) runs through all of them, extracting these dependencies into a file called linker.hints that lives in the directory kernel and modules reside in.

General Theory

So, with that background, it's time to explore the design. What if we could take that chaotic state of affairs and somehow tame it. If we could create macros that we could use to mark the plug and play data, as well as associate various binary bits with the plug and play attribute provided by the bus driver? What if we could create records in the modules similar to what is used to mark module dependencies? Then, kldxref(8) would be able to comb through this data, record it in linker.hints and we'd need little other modifications to the system to make this data readily accessible.

That's exactly what my changes do. New types of records are inserted into the special section of modules that describe the plug and play table in the driver. These records contain a header that contains the length of each table entry, a pointer to the first entry, and a tiny little "script" or "description" of the table that ties this binary data to the bus-provided plug and play data. Each bus in the system that is of the stylized type described above defines its own macros to help its client drivers mark the data. Since all the data is the same for all the drivers, this means client drivers don't need to reinvent the wheel. Since we also pass the length of each table entry, drivers can use the common pattern of having the common data first, followed by whatever other data it needs for each device in the table.

However, that leaves more work for the non-stylized busses. While a few of these drivers have been converted, many remain.

Details about the marking

The first place to look for the details is . The first user-visible bit is a macro MODULE_PNP_INFO
#define MODULE_PNP_INFO(d, b, unique, t, l, n)
"d" is the description of the table (more on that below). "b" is the name of the bus. Unique is a unique string (typically the driver name). "t" is a pointer to the plug and play table. "l" is the length of each entry in the table. "n" is the number of entries.

The description is of the general form  (TYPE:pnp_name[/pnp_name];)* where TYPE is one of the following:
  • U8      uint8_t element
  • V8      like U8 and 0xff means match an
  • G16    uint16_t element, any value >= matches
  • L16     uint16_t element, any value <= matches
  • M16    uint16_t element, mask of which of the following fields to use.
  • U16     uint16_t element
  • V16     like U16 and 0xffff means match any
  • U32     uint32_t element
  • V32     like U32 and 0xffffffff means match any
  • W32     Two 16-bit values with first pnp_name in LSW and second in MSW
  • Z       pointer to a string to match exactly
  • D       like Z, but is the string passed to device_set_descr()
  • P       A pointer that should be ignored
  • E       EISA PNP Identifier (in binary, but bus publishes string)
  • K       Key for whole table. pnp_name=value. must be last, if present.
The pnp_name "#" is reserved for other fields that should be ignored.

All this is a bit complicated. However, it can be simplified greatly for the buses that are stylized. For example PC Card, the PCCARD_PNP_INFO macro just takes a pointer to the first element and figures the rest out from there (you can see how in sys/dev/pccard/pccardvar.h).

kldxref(8)

Kldxref(8) has been modified to find all these entries. The above description is fairly complex, but covers all known tables in the current system. kldxref takes the above, and filters it into a much smaller subset by expanding different fields in a format more suited to quick parsing. It parses into the following format:
The format output is the simplified string from this routine in the same basic format as the pnp string, as documented in sys/module.h (and above). First a string describing the format is output, the a count of the number of records, then each record. The format string also describes the length of each entry (though it isn't a fixed length when strings are present).
type    Output          Meaning
   I       uint32_t        Integer equality comparison
   J       uint32_t        Pair of uint16_t fields converted to native byte order. The two fields both must match.
  G       uint32_t        Greater than or equal to
   L       uint32_t        Less than or equal to
  M       uint32_t        Mask of which fields to test. Fields that take up space increment the count. This field must be first, and resets the count.
   D       string          Description of the device this pnp info is for
   Z       string          pnp string must match this
   T       nothing         T fields set pnp values that must be true for the entire table.

Values are packed the same way that other values are packed in this file. Strings and int32_t's start on a 32-bit boundary and are padded with 0 bytes. Objects that are smaller than uint32_t are converted, without sign extension to uint32_t to simplify parsing downstream.

Current State

While the recording side is fairly well finished and committed to the tree, the rest of it is still up in the air. This section describes suggested future work for anybody wishing to help.

The easiest thing to do is to convert a few drivers to record this info. This conversion usually goes fairly quickly after you've found a similar driver that's been converted. Some drivers "save" space by matching the vendor code, for example, in code, while the device is matched from a table. When converting these drivers, you need to add the vendor code to each line in the table, and modify the code to get the vendor from the table.

Some buses have few enough drivers that it would be beneficial to adapt them to a stylized bus. simplebus being an obvious candidate. While most of the SoCs that have simplebus use a monolithic kernel, it's never too early to plan for a more generic and modular future. Some work in this area is in review.

There's three different strategies to use this data. First, the boot loader already reads in the linker.hints file. It could be modified to parse this data (it currently ignores it) and look at the PCI devices in the system. This leaves a number of holes, however, and loading drivers from the bootloader currently has significant performance issues. Second, the kernel could parse this file and load drivers as needed. However, this is far from straight forward in the kernel, since module loading needs to be queued until after / is available, and even after boot, some insertion events may happen in contexts that won't allow for modules to be loaded directly. Third, a user land program (perhaps devd(8)?) could parse the loader.hints file and create devd.conf scripts. USB currently has a program that will generate its hints based on ELF sections, a design which informed the current implementation. Its generator knows the format, which the current design hopes to avoid.

So a good start has been made, but more work is needed before we can ship only a MINIMAL kernel with modules. See this space for more info in the future.

20151226

Hard Float API coming soon by default to armv6

All the CPUs that FreeBSD supports have hard floating point in them. We've supported hard float for quite some time in the FreeBSD kernel. However, by default, we still use a soft-float ABI. All the binaries use hardware floating point to do the math, but the calling conventions between routines passes the floating point values in integer registers to remain compatible with the soft-float libraries of the past. A new armv6hf was created, but that caused some issues with some ports, and the meaning of 'soft float' sadly was ambiguous between the soft-float ABI, and the soft-float libraries that implement floating point when there's no hardware FPU.

Over the spring and summer, I fixed ld.so so that it  can load both soft ABI and hard ABI libraries on the same system, depending markings in the binaries themselves. Soft float ABI and hard float ABI binaries have different flags in the ELF headers, so it is relatively straight forward to know which is which. Over the summer, I committed changes to the kernel to pass the relevant flags from the header to user land (since for a variety of technical reasons, once you get to user land, it's impossible to open the binary you are executing in the general case). I had planned on committing the ld.so bits as well, but my job got busy and now it's winter.

So, in the coming days, I'll commit the first set of changes to move to armv6 as a hard float ABI by default. The kernel doesn't care: it can execute both. The new ld.so will allow you to transition through this change by allowing old, compat soft ABI libraries to co-exist on the system with new hard ABI libraries. This change alone isn't enough, but it will be good to get it out into circulation.

After that, a number of changes will follow. Similar to the LIB32 stuff for x86, mips and powerpc, there will be a LIBSOFT build that you can enable on armv6. This will create the libraries needed for the transition, and will be used if we need to generate compat binaries for this stuff (the hope is that the number of old binaries that need to run on the new system will be small enough that it can be treated as a special-needs case, not one that's needed by default). The normal armv6 build will switch to hard float ABI by default. armv6hf will remain in the build as a compatibility arch, and will be removed before FreeBSD 11 since it was never in FreeBSD 10 (and could never be in FreeBSD 10 due to compiler choices). TARGET_CPUTYPE will grow a new type or two for those folks with really special needs that need to generate wither soft-float libraries, or soft-float ABI libraries (and this will be the mechanism used to support LIBSOFT builds).

20151223

NanoBSD reved up for embedded

NanoBSD Enhancements

I've been experimenting with NanoBSD enhancements for embedded. Eventually, they will be in the mainline of NanoBSD, but for now I've segregated them in a separate embedded subdir. The goal is to drive creation of build-agnostic tools to help build images for the different systems that FreeBSD supports. I have a mix of embedded boards and qemu configurations. Many don't work, but I hit a milestone tonight. I was able to boot an image on my RPi built without privs using NanoBSD.

To try it out, you'll need to grab FreeBSD-current and from the top of the tree do
cd tools/tools/nanobsd/embedded
sh ../nanobsd.sh -c rpi.cfg

This will create a directory at the same level as your top level FreeBSD source called rpi-b. Under it will be obj/_.disk.image.rpi-b. You can dd this onto a SD card (any size) and boot it on your RPi-B. It will resize the last partition to span the rest of the disk on boot and be a generic system. There's still a few problems, and I'm still working out how to get packages onto the system at build time, but its useful enough that people may want to play with it. Enjoy.

P.S. Here's a dmesg from the boot:
U-Boot 2015.10 (Nov 09 2015 - 02:54:46 +0000)

DRAM:  480 MiB
RPI Model B rev2
MMC:   bcm2835_sdhci: 0
reading uboot.env

** Unable to read "uboot.env" from mmc0:1 **
Using default environment

In:    serial
Out:   lcd
Err:   lcd
Net:   Net Initialization Skipped
No ethernet found.
reading uEnv.txt
0 bytes read in 9 ms (0 Bytes/s)
Hit any key to stop autoboot:  0 
starting USB...
USB0:   Core Release: 2.80a
scanning bus 0 for devices... 3 USB Device(s) found
       scanning usb for storage devices... 0 Storage Device(s) found
       scanning usb for ethernet devices... 1 Ethernet Device(s) found
Booting from: mmc 0 ubldr.bin
reading ubldr.bin
214684 bytes read in 36 ms (5.7 MiB/s)
## No elf image at address 0x00200000
## Starting application at 0x00200000 ...
Consoles: U-Boot console  
Compatible U-Boot API signature found @1db474d0

FreeBSD/armv6 U-Boot loader, Revision 1.2
(imp@zooty, Wed Dec 23 17:23:10 MST 2015)

DRAM: 480MB
Number of U-Boot devices: 2
U-Boot env: loaderdev='mmc 0'
Found U-Boot device: disk
  Checking unit=0 slice= partition=... good.
Booting from disk0s3a:
/boot/kernel/kernel text=0x587d2c data=0x54f24+0xe639c syms=[0x4+0xc6460+0x4+0x94335]

Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [/boot/kernel/kernel]...               
Using DTB provided by U-Boot at address 0x100.
Kernel entry at 0x400180...
Kernel args: (null)
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2015 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
 The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 11.0-CURRENT #0 r292645 0ff2d15e64f9+ qbase/qtip/rpi/tip: Wed Dec 23 17:29:02 MST 2015
    imp@zooty:/usr/home/imp/FreeBSD/rpi-b/obj/arm.armv6/usr/home/imp/FreeBSD/head/sys/RPI-B arm
FreeBSD clang version 3.7.0 (tags/RELEASE_370/final 246257) 20150906
VT: init without driver.
sema_sysinit
CPU: ARM1176JZ-S rev 7 (ARM11J core)
 Supported features: ARM_ISA THUMB2 JAZELLE ARMv4 Security_Ext
 WB enabled LABT branch prediction enabled
  16KB/32B 4-way instruction cache
  16KB/32B 4-way write-back-locking-C data cache
real memory  = 503312384 (479 MB)
avail memory = 481800192 (459 MB)
random: entropy device external interface
kbd0 at kbdmux0
ofwbus0: 
simplebus0:  mem 0x20000000-0x20ffffff on ofwbus0
cpulist0:  on ofwbus0
cpu0:  on cpulist0
bcm2835_cpufreq0:  on cpu0
intc0:  mem 0xb200-0xb3ff on simplebus0
systimer0:  mem 0x3000-0x3fff irq 8,9,10,11 on simplebus0
Event timer "BCM2835-3" frequency 1000000 Hz quality 1000
Timecounter "BCM2835-3" frequency 1000000 Hz quality 1000
bcmwd0:  mem 0x10001c-0x100027 on simplebus0
gpio0:  mem 0x200000-0x2000af irq 57,59,58,60 on simplebus0
gpio0: read-only pins: 46-53.
gpio0: reserved pins: 48-53.
gpiobus0:  on gpio0
gpioled0:  at pin 16 on gpiobus0
gpioc0:  on gpio0
iichb0:  mem 0x205000-0x20501f irq 61 on simplebus0
iicbus0:  on iichb0
iic0:  on iicbus0
iichb1:  mem 0x804000-0x80401f irq 61 on simplebus0
iicbus1:  on iichb1
iic1:  on iicbus1
spi0:  mem 0x204000-0x20401f irq 62 on simplebus0
spibus0:  on spi0
bcm_dma0:  mem 0x7000-0x7fff,0xe05000-0xe05fff irq 24,25,26,27,28,29,30,31,32,33,34,35,36 on simplebus0
mbox0:  mem 0xb880-0xb8bf irq 1 on simplebus0
sdhci_bcm0:  mem 0x300000-0x3000ff irq 70 on simplebus0
mmc0:  on sdhci_bcm0
uart0:  mem 0x201000-0x201fff irq 65 on simplebus0
uart0: console (115200,n,8,1)
vchiq0:  mem 0xb800-0xb84f irq 2 on simplebus0
vchiq: local ver 8 (min 3), remote ver 8.
pcm0:  on vchiq0
bcm283x_dwcotg0:  mem 0x980000-0x99ffff irq 17 on simplebus0
usbus0 on bcm283x_dwcotg0
fb0:  on ofwbus0
fbd0 on fb0
VT: initialize with new VT driver "fb".
fb0: 656x416(656x416@0,0) 24bpp
fb0: fbswap: 0, pitch 1968, base 0x1e08c000, screen_size 818688
cryptosoft0: 
Timecounters tick every 10.000 msec
IPsec: Initialized Security Association Processing.
usbus0: 480Mbps High Speed USB v2.0
bcm2835_cpufreq0: ARM 700MHz, Core 250MHz, SDRAM 400MHz, Turbo OFF
ugen0.1:  at usbus0
uhub0:  on usbus0
mmc0: CMD8 failed, RESULT: 1
mmcsd0: 513MB  at mmc0 41.6MHz/4bit/65535-block
Trying to mount root from ufs:/dev/mmcsd0s3a [ro]...
warning: no time-of-day clock registered, system time will not be set accurately
uhub0: 1 port with 1 removable, self powered
ugen0.2:  at usbus0
uhub1:  on usbus0
uhub1: MTT enabled
uhub1: 3 ports with 2 removable, self powered
random: unblocking device.
ugen0.3:  at usbus0
smsc0:  on usbus0
smsc0: chip 0xec00, rev. 0002
miibus0:  on smsc0
ukphy0:  PHY 1 on miibus0
ukphy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
ue0:  on smsc0
ue0: Ethernet address: b8:27:eb:f1:62:e6
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
Growing root partition to fill device
GEOM_PART: mmcsd0s3 was automatically resized.
  Use `gpart commit mmcsd0s3` to save changes or `gpart undo mmcsd0s3` to revert them.
mmcsd0s3 resized
mmcsd0s3a resized
super-block backups (for fsck_ffs -b #) at:
 556192, 667424, 778656
/etc/rc: WARNING: hostid: unable to figure out a UUID from DMI data, generating a new one
Setting hostuuid: 901c1969-a9d5-11e5-996d-b827ebf162e6.
Setting hostid: 0x45acda89.
No suitable dump device was found.
Starting file system checks:
/dev/mmcsd0s3a: FILE SYSTEM CLEAN; SKIPPING CHECKS
/dev/mmcsd0s3a: clean, 181490 free (26 frags, 22683 blocks, 0.0% fragmentation)
/dev/mmcsd0s2: FILE SYSTEM CLEAN; SKIPPING CHECKS
/dev/mmcsd0s2: clean, 32726 free (6 frags, 4090 blocks, 0.0% fragmentation)
Mounting local file systems:.
Setting hostname: nanobsd-rpi-b.
Setting up harvesting:[UMA],[FS_ATIME],SWI,INTERRUPT,NET_NG,NET_ETHER,NET_TUN,MOUSE,KEYBOARD,ATTACH,CACHED
Feeding entropy:eval: cannot create /boot/entropy: Read-only file system
smsc0: chip 0xec00, rev. 0002
ue0: link state changed to DOWN
ue0: link state changed to UP
Starting Network: lo0 ue0.
lo0: flags=8049 metric 0 mtu 16384
 options=600003
 inet6 ::1 prefixlen 128 
 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
 inet 127.0.0.1 netmask 0xff000000 
 groups: lo 
 nd6 options=21
ue0: flags=8843 metric 0 mtu 1500
 options=80009
 ether b8:27:eb:f1:62:e6
 media: Ethernet autoselect (100baseTX )
 status: active
 nd6 options=29
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
Starting devd.
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
Starting dhclient.
DHCPDISCOVER on ue0 to 255.255.255.255 port 67 interval 5
DHCPOFFER from 10.0.0.5
DHCPREQUEST on ue0 to 255.255.255.255 port 67
DHCPACK from 10.0.0.5
bound to 10.0.0.65 -- renewal in 3600 seconds.
add net fe80::: gateway ::1
add net ff02::: gateway ::1
add net ::ffff:0.0.0.0: gateway ::1
add net ::0.0.0.0: gateway ::1
Generating host.conf.
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
Creating and/or trimming log files.
Starting syslogd.
Setting date via ntp.
24 Dec 01:06:34 ntpdate[457]: step time server 204.9.54.119 offset 2122.146331 sec
Starting casperd.
Clearing /tmp (X related).
Updating motd:.
Mounting late file systems:.
Configuring vt: blanktime.
Starting cron.
/etc/rc.conf: 1.freebsd.pool.ntp.org: not found
Starting background file system checks in 60 seconds.
override rw-rw-r--  730/730 for /firstboot? 

Thu Dec 24 01:06:47 UTC 2015

FreeBSD/arm (nanobsd-rpi-b) (ttyu0)

login: root
Dec 24 01:06:50 nanobsd-rpi-b login: ROOT LOGIN (root) ON ttyu0
FreeBSD 11.0-CURRENT (RPI-B) #0 r292645 0ff2d15e64f9+ qbase/qtip/rpi/tip: Wed Dec 23 17:29:02 MST 2015

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

Edit /etc/motd to change this login announcement.
root@nanobsd-rpi-b:~ # mount -uw /
root@nanobsd-rpi-b:~ # rm /firstboot
root@nanobsd-rpi-b:~ # uname -a
FreeBSD nanobsd-rpi-b 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r292645 0ff2d15e64f9+ qbase/qtip/rpi/tip: Wed Dec 23 17:29:02 MST 2015     imp@zooty:/usr/home/imp/FreeBSD/rpi-b/obj/arm.armv6/usr/home/imp/FreeBSD/head/sys/RPI-B  arm
root@nanobsd-rpi-b:~ # uptime
 1:07AM  up 1 min, 1 users, load averages: 0.87, 0.39, 0.16
root@nanobsd-rpi-b:~ # ifconfig
lo0: flags=8049 metric 0 mtu 16384
        options=600003
        inet6 ::1 prefixlen 128 
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
        inet 127.0.0.1 netmask 0xff000000 
        groups: lo 
        nd6 options=21
ue0: flags=8843 metric 0 mtu 1500
        options=80009
        ether b8:27:eb:f1:62:e6
        inet 10.0.0.65 netmask 0xffffff00 broadcast 10.0.0.255 
        media: Ethernet autoselect (100baseTX )
        status: active
        nd6 options=29
root@nanobsd-rpi-b:~ # ntpdate 0.freebsd.pool.ntp.org
load: 0.48  cmd: ntpdate 671 [select] 8.16r 0.05u 0.04s 0% 3112k
24 Dec 01:07:44 ntpdate[671]: adjust time server 69.164.201.165 offset 0.001943 sec
root@nanobsd-rpi-b:~ # exit
logout

FreeBSD/arm (nanobsd-rpi-b) (ttyu0)

login: 

20131117

Building old-school TiVo build tools on FreeBSD 9.2-stable

Intro

As long-term readers of my blog know, I've been nursing along a TiVo HR10-250 for the past few years. It works great for the low-quality material that my younger son loves to watch, plus I can harvest video off of it with ease.

Recently, we switched up how it was connected to our TV (and indeed, got a new TV too). During this process, we lost the ability to display subtitles. Since my wife and I like to watch The Daily Show and other similar shows upstairs without going downstairs to the big TV with the HD DirecTV player, and the environment upstairs can be a bit noisy, subtitles are quite useful.

So, after crawling around the DealDatabase forums for a bit, I found a good program called tivovbi. It works really well for displaying closed captioning. However, I used a binary I found on the forum. Nothing is more annoying than a program you download from a forum that randomly core dumps for reasons that are totally mysterious.

I can't even hack it to do anything since I have no TiVo build tools.  Looking for tools online, I can't really find anything that isn't just a Linux binary.  The Linux binaries have issues with the FreeBSD linux ABI implementation, owing in large part to their age (binaries from 10 years ago have some issues, I think with just the packages are needed having a subtle incompatibility).

So what should I do. I could create a virtualbox VM and run linux. But then I'd be running Linux, and copying back and forth to a VM is always a hassle in some way.

So, the other alternative is to build the tools from source. I thought it would be easy to do this, but there's a number of issues with it, so I thought I'd write up my experience. This is on a FreeBSD 9.2-stable system on amd64. That last bit will turn out to be important in a bit, because nothing was easy and simple on this project...

After reading through these instructions, I can't help but marvel at how this lack of integration is tolerated, but to be fair, this is building tools that are nearly a decade old at this point and I did have to kludge around lack of support for 64-bit x86 in gcc... This is nearly 60 separate commands to type. Yuck. Also, looking at the layout in chrome, many of the line breaks have liberties taken with them, so your best bet may be to cut and paste much of what I'm doing here...

Locating the tools

Tivo Utils has a bunch of useful links. Including the linux binaries that I've had issues with. Thankfully, there's a shell script called 'build_mips_x_compiler.sh' which builds all the tools and the basic libraries. I thought I could just run it and have everything built. As with everything else in this project, this wasn't so much the case. So I wound up doing a lot of things by hand.

The first bit of the script fetches all the source tar balls. The gnu stuff has had long-term stable paths, so they fetched. However the TiVo linux didn't transfer, since it was in a new location. In fact, it was also for 4.0, and my TiVo was running 6.4a. So, I had to grab that from TiVo linux downloads page. The Linux 6.4 download was exactly what I needed to grab. Once I had these in place, I was ready to start building. You also need binutils 2.13Gcc 3.0 (yes, 3.0!), glibc 2.2.3, and glibc 2.2.3 linuxthreads support.

Also, I'm installing all the tools in ~/tivo/tools tree, and building them from ~/tivo/toolchain. Fetch all of the above linked tarballs into ~/tivo/toolchain (or whatever you want). Now that we've found the tarballs, we can start with the builds. I'll assume the following environment variables are set. TARGET is set to "mips-TiVo-linux" and PREFIX is set to "$HOME/tivo/tools". I've also added ${PREFIX}/bin to my PATH (I didn't from the start, and got quite far before it mattered). I also had gnu make installed as gmake from ports.

Building Tools

Binutils 2.13

Binutils 2.13 is almost trivial to build:
cd ~imp/toolchain
tar xvfz binutils-2.13.tar.gz
mkdir build-buinutils
cd build-binutils
../binutils-2.13/configure  --target=$TARGET --prefix=$PREFIX
gmake -j 20 all
gmake install
cd ..

gcc 3.0 stage 1

gcc 3.0 stage 1 took a lot of trial and error to create. Turns out, there's no support for FreeBSD 9 in this tarball. That's trivial to add, and I've provided some patches. However, the next problem is that FreeBSD/amd64 isn't supported. This problem turns out to be more difficult to overcome. So you have to configure for FreeBSD/i386 (or backport amd64 support, which I thought would be too hard, so I didn't do it). This means you need to have a 32-bit compiler. After all the talk about making cc -m32 working, I thought I could just do gmake CC="cc -m32". This failed, however. The 32-bit applications dumped core, meaning that gcc couldn't complete its bootstrap process. I wound up having to use FreeBSD's xdev to do it:
pushd ~/FreeBSD/svn/stable/9
sudo make xdev XDEV=i386 XDEV_ARCH=i386 WITHOUT_CLANG=t
popd
Once we have that in place, we can build gcc. Except that it doesn't build quite right. We need to add some additional patches. One to work around a weirdness in the obstack implementation where it relied on an illegal lvalue autoincrement, and one to work around crazy sh that's likely bogus in fixincl. All of these are included in the above patch.
mkdir build-gcc
cd build-gcc
../gcc-3.0/configure --target $TARGET --prefix $PREFIX --without-headers --with-newlib --disable-shared --enable-languages=c --host i386-foo-freebsd9
gmake CC=/usr/i386-freebsd/usr/bin/cc all-gcc
gmake CC=/usr/i386-freebsd/usr/bin/cc install-gcc
If you wanted to see if -m32 worked, you could skip the make xdev step above and substitute CC="cc -m32" in the two gmake commands. I've also tested values up to 20 for -j for at least the first command.

Building the Linux Kernel headers

The following comes pretty much verbatim from the build_mips_x_compiler.sh and have been verified to work. You'll need to grab this patch for these instructions to work. It works around an expr difference, as well a really cheap kludge to get autoconf.h generated. Also, I had to install the bash port, and create a symlink from /bin/bash to /usr/local/bin/bash, which I've not put inline...
tar xf TiVo-6.4-linux-2.4.tar.gz
cd linux-2.4
patch -p0 < ../tivo-linux-2.4.diff
yes "" | gmake ARCH=mips CROSS_COMPILE=mips-TiVo-linux config
gmake ARCH=mips CROSS_COMPILE=mips-TiVo-linux include/linux/version.h
mkdir $PREFIX/$TARGET/include
cp -rf include/linux $PREFIX/$TARGET/include
cp -rf include/asm-mips $PREFIX/$TARGET/include/asm
which will be enough to get us to the next step...  Woof, maybe I should just make a script for all this stuff... With so many fiddly bits, I'm not sure that's a good idea.

Building gmake 3.80!

Newer versions of gmake don't grok the Makefiles that glibc 2.2.3 generates. All kinds of weird errors and odd behavior. So, to make progress, you'll need to build gmake.
fetch ftp://ftp.gnu.org/gnu/make/make-3.80.tar.gz
tar xf make-3.80.tar.gz
cd make-3.80
./configure
make
cp make ~/bin/gmake380
cd ..
I didn't bother installing it, since I just need it for this diversion so I copied into my bin dir, that I have in my path.

Building glibc 2.2.3

Now we're on to glibc. Things have been smooth sailing up to this point. With glibc, we have to extract, configure, build, fix the build oops, build again, fix some info files, then install. Woof! Sure makes for a difficult to reproduce experience. And those are the build on linux instructions... Apparently there's a lot of host leakage that's making things somewhat difficult to reproduce... but so far that appears to be only with gmake 3.82. gmake 3.80 works much better. More patches needed.
tar xf glibc-2.2.3.tar.gz
tar xf glibc-linuxthreads-2.2.3.tar.gz -C glibc-2.2.3
env CC=mips-TiVo-linux-gcc ../glibc-2.2.3/configure --host=$TARGET --prefix=$PREFIX --disable-debug --disable-profile --enable-add-ons --with-headers=${PREFIX}/${TARGET}/include
gmake380
sed -i.old -e 's/elf32-bigmips/elf32-tradbigmips/' elf/rtld-ldscript
gmake380
gmake380 install
cd ..

Munging things around before the second assault  on gcc for its stage 2

Don't know why the original instructions take this time rearrange the deck chairs, but it seems to be necessary.
mv ${PREFIX}/${TARGET}/include/asm ${PREFIX}/include
mv ${PREFIX}/${TARGET}/include/linux ${PREFIX}/include
rm -r ${PREFIX}/${TARGET}/include
rm -r ${PREFIX}/${TARGET}/lib
ln -s ${PREFIX}/include ${PREFIX}/${TARGET}/include
ln -s ${PREFIX}/lib ${PREFIX}/${TARGET}/lib

Build gcc 3.0 stage 2

Now that we have everything else setup, it is time to build the second stage of gcc. Alas, gcc 4.2.1 doesn't allow constructs like (a ? b : c) = d, which gcc 3.0 uses to implement C++. So, no g++ for me. If you want g++, you'd have to build the gcc34 port... The rest is almost boring after all the other hoops we jumped through:
mkdir build-gcc2
cd build-gcc2
../gcc-3.0/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c --host=i386-foo-freebsd9
gmake CC=/usr/i386-freebsd/usr/bin/cc all
gmake CC=/usr/i386-freebsd/usr/bin/cc install
cd ..

Building stuff

Now, it is time build things...  I'll write more blog entries about that...

20120607

Wish me luck: taking the git plunge

Wish me luck.

I just typed the following commands:

  • git clone https://github.org/freebsd/freebsd-head.git
  • cd freebsd-head
  • git branch army
  • git checkout army
and started my own local branch.  Wish me luck.  Oh, I've said it, but with git, I think I might need it.  I actually didn't type exactly the above, but that's what I should have typed.  git reset seems to have been my friend.  We'll see next time I pull from github...  and if I can get the rebase command to work for me better than mercurial has been working for me at work.

Now, to figure out how to do  a similar thing to patch queues, except I really want to just correct commits rather than use a whole different set of commands.

20120603

Rearranging the deck chairs in the ARM port

Recently, I've been trying to catch up with some of the technical debt that the FreeBSD/arm port has accumulated.  Some of that technical debt was my fault, of course, but some of it wasn't.  I don't really much care whose fault things were,  but I would like to get things cleaned up.  Some of these are paths not taken.  Some are porting shims that never got properly connected.  There's also some features that were poo-poo-ed by some (including me) years ago that seem to make more sense now.

None of this stuff is terribly sexy.  Some of it will be addressed by the summer of code project that's working its way through some of the maze of twisty passages in initarm() that are subtly different between the different boards for no good reason.

We have no common place for boot loader code.  Some arm ports do use a common routine to fake up just enough metadata that debugging and other symbols work.  Some arm ports assume a full /boot/loader is present.  However, there's no common facility for getting information from via the Linux boot protocol, nor is there any provisions for having multiple boards supported by a single kernel.  There's no uniform interface to get this information that might be passed in by other means.  There's no real way for a board to get control early enough to get at meta-data a custom boot loader might pass in.

The first big thing that I'd like to comment on is a small change to the interface between locore.S' _start routine and the first port-specific code in initarm.  I've preserved the first 4 registers that were passed in on boot to _start().  Before, there'd be no way to access the Linux ATAGs, for example, by a port since these are passed in as arg 3.  To allow for future expansion, I'm just passing in one structure now.

In the coming weeks, I'll be implementing routines to parse these arguments based on standard boot protocols, while allowing customization for special needs.

In the coming months, I plan to expand our support for having multiple boards based on a single Atmel SoC.  Once I have the one at a time SoC code working, I hope to get multiple SoCs working in one kernel.  While the extra 'bloat' isn't optimal for many users, the convenience of being able to boot one kernel for installation, or trying out the system, is a feature that's been much requested.  I've already eliminated the need to have a compiled-in master clock frequency, with improved main clock detection with fallback for people using unconventional frequencies.

I'm also interested in sweeping into the tree many of the Atmel arm changes that have been accumulating in the PR database.  Some of these will be easy to integrate, while others may be difficult due to drift from the original submission.

Once we get a good baseline, I hope to merge these changes into 9.x and 8.x.  To date, the interfaces that have change have been purely internal ones we do not support.  External users may experience some bumpy waves if they haven't been working to get their changes merged upstream.  The more that you've submitted, the more I'm likely to go the extra mile to help smooth any transitions.  With luck, 8.3 and 9.2 will both benefit from these efforts.

20110117

FreeBSD/mips for Cavium Octeon

I've recently improved the ABI selection in FreeBSD/mips. Now it is all handled via MACHINE_ARCH or TARGET_ARCH. mipsel and mipseb are the o32 32-bit versions. mips64eb and mips64el are for n64 64-bit versions.

I've knocked together a script for building an image for the Cavium Octeon eval boards that have CF that can boot using uboot from SDK 1.9.0 and 2.0.0 (and likely earlier versions, but I've not tested them). It creates two partitions: a FAT partition for the kernel and BSD partition for the rest of FreeBSD. It also takes care of building a big endian ufs system on a little endian system. You can find the script here. I've also create an image as well you can grab here. The script contains instructions for how to create the CF image.

Enjoy

20101202

New FreeNAS beta snapshot released (r5648)

We've released the next beta snapshot of FreeNAS.

You can read the release notes for all the details.

Here's a highlight of the issues that we've fixed since the last beta (r5606):
  • Upgrades from prior FreeNAS 8 beta releases are now supported.
  • zfs creation failures have been fixed. The gui would indicate it succeeded, but you couldn't share it.
  • ufs creation failures have been fixed.
  • booting off USB or SCSI cdrom is now supported.
  • Many disk initialization errors that showed up as odd failures have been corrected.
  • lagg has been introduced.
  • Errors in the network screen have been corrected.
  • The storage wizard no longer says 'of X' when creating the storage unit. This eliminates the confusing 1 of 3 -> 2 of 2 dialog heading.
  • Improved compatibility with IE and Safari.
  • The installer has been streamlined.
Also, I was pleasantly surprised today when I logged in and found 19 comments from my last blog entry. I'm not used to so many, so hadn't been checking. I'll be checking more here. I'll also write a blog entry to address many of the issues raised in them.


You can download the latest from sourceforge.