I've had several requests for pictures of my son playing in the sandbox. I'll go one better and show pictures of my son and I playing in the sandbox. My wife took them just after I filled it with sand.
Now, all I have to do is make a lid for the box to keep the local cats and racoons out.
20080829
20080828
Sandbox
I debated writing about this. After all, it isn't about hacking code. Instead, it is about hacking together a sandbox. It is about making stupid design choices and then over engineering "solutions" to those problems. It is a cautionary tale about doing the design right from the start and sometimes "free" lumber costs a lot in time and effort.
So, I wanted to make a 4'x4' (just a little over 1m x 1m) sandbox for my 2 year old. He loves sand in the parks and I wanted him to have a place to play in the back yard. My wife suggested we just get one of those turtles, but I wouldn't hear of it. After all, I had a bunch of 2x4's in the garage. Why pay good money for a plastic turtle when I could just build a simple box out of the 2x4's.
I wanted a 4" depth of sand, so I figured I'd have to stack the 2x4's. Rather than just buy a couple of 2x8's and bolt them together, I had to use 2x4's. Of course, I had planned on stacking them, but what I hadn't planned well was how to do it. I wound up with small 2x2's as wooden cleats. So I get the box put together. It was fairly straight forward to do this. I connected the two halves of the box with short 2x2's. I proudly showed it to my wife who immediately said "those sharp edges sticking out look dangerous." She was talking about the 2x2's. Once I saw it from her point of view, I realized she was right.
Now, rather than spend $8.00 on 2 2x6's or 2x8's for the box, I spent $9.86 on 12 6" ceramic coated screws to hold the box together. I then drilled holes and recessed the heads (why? I don't know, just seemed like a good idea even though they were on the bottom). I drove the screws in and removed the 2x2 cleats. The box looked great! And I even managed to add the trip onto another trip to a near by store, so I didn't blow a ton of time and gas getting them. That was luck, pure and simple, since usually for things like this I'm making another trip...
I then went to put it where we'd agreed and realized I had no bottom. I had to do something about a bottom. I thought I'd just use some of the yard fabric I had left over from all my landscaping chores. Turns out that I left all that at my old house. So instead I took and old tarp with a tear in it and cut a 4'x4' section and laid it on the ground and put the sandbox on top of it. I then filled it with the play sand I'd been lugging around in my car for a week while I finished the box. Time will tell if I secured things in place well enough or not. I was planning on going to the store to get a bunch of rebar to drive into the ground to keep the box from moving, but I realized just how crazy this was getting and I just made a couple of wooden wedges to hold the thing in place. We'll see how that works out, but they are likely good enough, and were scrap anyway...
In the end, I spent 4 hours building this box. While a turtle would have saved me a bunch of time, and would likely have cost about the same as what I spent on wood, nails and screws (all but the last one had already been purchased, but I did pay for them). I'd have been done in 30 minutes. Of course, I wouldn't have gotten to use the power tools, and I really like the idea of building things for my son. I put the sand in tomorrow and we'll see how well he likes the box.
So, am I crazy? Did I go overboard on trying to save a nickle only to cost myself a ton of time? Maybe. Did I have fun putting it together? You bet! Was it worth it? Yes...
So, I wanted to make a 4'x4' (just a little over 1m x 1m) sandbox for my 2 year old. He loves sand in the parks and I wanted him to have a place to play in the back yard. My wife suggested we just get one of those turtles, but I wouldn't hear of it. After all, I had a bunch of 2x4's in the garage. Why pay good money for a plastic turtle when I could just build a simple box out of the 2x4's.
I wanted a 4" depth of sand, so I figured I'd have to stack the 2x4's. Rather than just buy a couple of 2x8's and bolt them together, I had to use 2x4's. Of course, I had planned on stacking them, but what I hadn't planned well was how to do it. I wound up with small 2x2's as wooden cleats. So I get the box put together. It was fairly straight forward to do this. I connected the two halves of the box with short 2x2's. I proudly showed it to my wife who immediately said "those sharp edges sticking out look dangerous." She was talking about the 2x2's. Once I saw it from her point of view, I realized she was right.
Now, rather than spend $8.00 on 2 2x6's or 2x8's for the box, I spent $9.86 on 12 6" ceramic coated screws to hold the box together. I then drilled holes and recessed the heads (why? I don't know, just seemed like a good idea even though they were on the bottom). I drove the screws in and removed the 2x2 cleats. The box looked great! And I even managed to add the trip onto another trip to a near by store, so I didn't blow a ton of time and gas getting them. That was luck, pure and simple, since usually for things like this I'm making another trip...
I then went to put it where we'd agreed and realized I had no bottom. I had to do something about a bottom. I thought I'd just use some of the yard fabric I had left over from all my landscaping chores. Turns out that I left all that at my old house. So instead I took and old tarp with a tear in it and cut a 4'x4' section and laid it on the ground and put the sandbox on top of it. I then filled it with the play sand I'd been lugging around in my car for a week while I finished the box. Time will tell if I secured things in place well enough or not. I was planning on going to the store to get a bunch of rebar to drive into the ground to keep the box from moving, but I realized just how crazy this was getting and I just made a couple of wooden wedges to hold the thing in place. We'll see how that works out, but they are likely good enough, and were scrap anyway...
In the end, I spent 4 hours building this box. While a turtle would have saved me a bunch of time, and would likely have cost about the same as what I spent on wood, nails and screws (all but the last one had already been purchased, but I did pay for them). I'd have been done in 30 minutes. Of course, I wouldn't have gotten to use the power tools, and I really like the idea of building things for my son. I put the sand in tomorrow and we'll see how well he likes the box.
So, am I crazy? Did I go overboard on trying to save a nickle only to cost myself a ton of time? Maybe. Did I have fun putting it together? You bet! Was it worth it? Yes...
20080827
Low hanging fruit
Tonight was low hanging fruit night. I went through all the PRs that had "pccard" or "cardbus" and committed the easiest of the fixes. When I did this with USB last year there were maybe 50 of them I committed over the course of a few weeks. For PC Card and CardBus, there were maybe 5 or 6 that I was able to commit. And a similar number of stale ones. Unlike USB, there's only a few PC Card and CardBus bugs in the PR database, at least that are flagged as such.
I find this surprising, since any CardBus card that uses I/O ports hasn't worked in a while. And CardBus card whose CIS is stored in "Expansion ROM" won't work. There's a bunch of problems with some of the newer "ed" cards as well for PHY handling. At least I've recently solved some of the power issues, or I'd be feeling pretty low about the state of affairs. Fortunately, most people want a CardBus slot for a wireless card these days, and atheros chipsets are memory mapped.
The ExpressCard stuff is stalled at the moment while I ponder a difficult problem with resource allocation. There's likely a simple solution to this problem that I'm not seeing, but it likely requires thinking a little outside the box to make it totally effective.
I find this surprising, since any CardBus card that uses I/O ports hasn't worked in a while. And CardBus card whose CIS is stored in "Expansion ROM" won't work. There's a bunch of problems with some of the newer "ed" cards as well for PHY handling. At least I've recently solved some of the power issues, or I'd be feeling pretty low about the state of affairs. Fortunately, most people want a CardBus slot for a wireless card these days, and atheros chipsets are memory mapped.
The ExpressCard stuff is stalled at the moment while I ponder a difficult problem with resource allocation. There's likely a simple solution to this problem that I'm not seeing, but it likely requires thinking a little outside the box to make it totally effective.
20080826
Summer tree cleaning
As you may know, I'm a user of the p4 side repository to do large code development. With the switch to svn, I wasn't sure I'd still need to do that, so I let my trees there go for a while. It is clear to me that I'll need to use p4 a little while longer. So, I cleaned up my newcard tree.
Why do I need to cleanup at all? That's a good question. You'd think that you'd only have code cooking in the tree that was destined to be committed, so no cleanup is needed. Merging conflicts, sure, but no cleanup. Well, it turns out that sometimes perforce doesn't do quite the right thing when there's a loop back of new files into FreeBSD. If I create a file in perforce, and then later merge it into FreeBSD, then the $FreeBSD$ tag is messed up. Over time, you get lots of these files in the perforce tree, and you have to basically just copy the FreeBSD version over them.
The other reason to clean up is that code can cook for too long. I have several projects in my newcard tree that just didn't work out. I didn't get them into the tree quickly enough and the problems they were designed to clean up have been solved in other ways. Or they fixed problems in the MD code, and now that FreeBSD has grown more machines more code needs to be changed. Sometimes you change the new MD code. Other times, you just junk the old stuff since the improvements were so marginal that it isn't worth carrying those stones in your kit bag anymore.
Sometimes projects are only half-baked. I had a number of interesting ideas that turned out to not be such a good idea. That turned out to not be a big enough savings, or that some other key developer in the project didn't like. It happens. Some ideas are great, while others seem to be grating on others.
So all of these are reasons to cleanup the tree. I've managed to reduce my diffs from 200k down to 100k. Most of the 100k that's left could easily be described as half-baked. The biggest half-baked thing is a port of the NetBSD improvements to mii. The second biggest are a collection of hacks and bug fixes to the pccard/cardbus layer. Those always take a lot of time to sort out.
It is one of the more pedestrian things that I need to do when hacking. But if the litter piles up too high, it becomes increasingly difficult to see what should go into the tree, and what shouldn't so nothing does and many of my cool hacks don't benefit people, and I don't benefit from the wider exposure of the code. Nobody tests my private tree but me... Everybody notices when you put something even a little stinky into the main FreeBSD tree.
I debated about not blogging about it. However, one reason people have told me they read my blog is that they learn how to be better engineers from some of the things I do. They usually don't tell me if they are emulating things I do because they think they are good, or if they are avoiding the things I do because they think they are bad. Maybe a little of both... Documenting the mundane from time to time may bring better balance. Or it may put my readers to sleep... It is hard to say without feedback...
Why do I need to cleanup at all? That's a good question. You'd think that you'd only have code cooking in the tree that was destined to be committed, so no cleanup is needed. Merging conflicts, sure, but no cleanup. Well, it turns out that sometimes perforce doesn't do quite the right thing when there's a loop back of new files into FreeBSD. If I create a file in perforce, and then later merge it into FreeBSD, then the $FreeBSD$ tag is messed up. Over time, you get lots of these files in the perforce tree, and you have to basically just copy the FreeBSD version over them.
The other reason to clean up is that code can cook for too long. I have several projects in my newcard tree that just didn't work out. I didn't get them into the tree quickly enough and the problems they were designed to clean up have been solved in other ways. Or they fixed problems in the MD code, and now that FreeBSD has grown more machines more code needs to be changed. Sometimes you change the new MD code. Other times, you just junk the old stuff since the improvements were so marginal that it isn't worth carrying those stones in your kit bag anymore.
Sometimes projects are only half-baked. I had a number of interesting ideas that turned out to not be such a good idea. That turned out to not be a big enough savings, or that some other key developer in the project didn't like. It happens. Some ideas are great, while others seem to be grating on others.
So all of these are reasons to cleanup the tree. I've managed to reduce my diffs from 200k down to 100k. Most of the 100k that's left could easily be described as half-baked. The biggest half-baked thing is a port of the NetBSD improvements to mii. The second biggest are a collection of hacks and bug fixes to the pccard/cardbus layer. Those always take a lot of time to sort out.
It is one of the more pedestrian things that I need to do when hacking. But if the litter piles up too high, it becomes increasingly difficult to see what should go into the tree, and what shouldn't so nothing does and many of my cool hacks don't benefit people, and I don't benefit from the wider exposure of the code. Nobody tests my private tree but me... Everybody notices when you put something even a little stinky into the main FreeBSD tree.
I debated about not blogging about it. However, one reason people have told me they read my blog is that they learn how to be better engineers from some of the things I do. They usually don't tell me if they are emulating things I do because they think they are good, or if they are avoiding the things I do because they think they are bad. Maybe a little of both... Documenting the mundane from time to time may bring better balance. Or it may put my readers to sleep... It is hard to say without feedback...
20080825
T-Mobile Dash experiment
I have two cell phones. One of this is my iPhone, made by Apple and running Apple's version of FreeBSD. The other is the T-Mobile Dash. I usually use my iPhone, but this weekend I was using the Dash to see how well it worked. It was no better or worse than the iPhone in the one area that I'd hoped it would be better at: call quality.
In the process of trying it out, I discovered the uipaq driver in FreeBSD. I wanted to use the Dash as a tethered phone. It is the whole reason I got it. Since the iPhone doesn't officially support tethering, I thought I'd give the Dash a try.
The uipaq driver was added to FreeBSD 7.0, ported from NetBSD which ported it from OpenBSD. Its roots go way back to the old Compaq iPaqs that were made years ago. This same basic interface has gone through only minor evolution in the interceding years. Unfortunately, I wasn't able to make it work with my phone due to some minor issues else where.
In the process of trying, I discovered there was no man page, so I snagged one from NetBSD and hacked it to account for the differences with FreeBSD. In searching how to setup the phone as a ppp link, I stumbled into a PR that greatly expanded the number of devices the driver recognizes and made it committable, I discovered that it wasn't built as a module, and I discovered that an old PDA I had in the garage would work with this driver, in addition to my HCT dash. All the easy problems I fixed...
So I moved the rock up the hill a little. I'll try another day to see if I can track down the issues that were else where in the kernel and see if I can punch entirely through to the other side. The lack of a tether solution has been the biggest disappointment with the iphone that I've had. While a number of interesting hackers are possible in that area, none of them are as easy and as simple as my old Sprint Samsung SPC-7600 was. The Dash also has bluetooth, which I'll give a spin after I can get it to connect with the wires...
None of this would be necessary if Apple didn't have such a tight control on what one can and cannot put on the phone. Well, control isn't the real issue. Rather, the issue is that they choose to control it in a way I don't like. If they controlled it in every way the same way I wanted to configure it, I doubt very many people would care... Since they don't, a lot of people are very interested in hacking it... but that's starting to get off topic...
In the process of trying it out, I discovered the uipaq driver in FreeBSD. I wanted to use the Dash as a tethered phone. It is the whole reason I got it. Since the iPhone doesn't officially support tethering, I thought I'd give the Dash a try.
The uipaq driver was added to FreeBSD 7.0, ported from NetBSD which ported it from OpenBSD. Its roots go way back to the old Compaq iPaqs that were made years ago. This same basic interface has gone through only minor evolution in the interceding years. Unfortunately, I wasn't able to make it work with my phone due to some minor issues else where.
In the process of trying, I discovered there was no man page, so I snagged one from NetBSD and hacked it to account for the differences with FreeBSD. In searching how to setup the phone as a ppp link, I stumbled into a PR that greatly expanded the number of devices the driver recognizes and made it committable, I discovered that it wasn't built as a module, and I discovered that an old PDA I had in the garage would work with this driver, in addition to my HCT dash. All the easy problems I fixed...
So I moved the rock up the hill a little. I'll try another day to see if I can track down the issues that were else where in the kernel and see if I can punch entirely through to the other side. The lack of a tether solution has been the biggest disappointment with the iphone that I've had. While a number of interesting hackers are possible in that area, none of them are as easy and as simple as my old Sprint Samsung SPC-7600 was. The Dash also has bluetooth, which I'll give a spin after I can get it to connect with the wires...
None of this would be necessary if Apple didn't have such a tight control on what one can and cannot put on the phone. Well, control isn't the real issue. Rather, the issue is that they choose to control it in a way I don't like. If they controlled it in every way the same way I wanted to configure it, I doubt very many people would care... Since they don't, a lot of people are very interested in hacking it... but that's starting to get off topic...
20080823
Quick device_get_children cleanup
Hans Petter Selasky submitted a bug against the rather poor error handling of device_get_children a while ago. When the usb4bsd stuff he's trying to get into the tree was posted for review, one of the issues was with device_get_children() as it related to device_delete_children().
This reminded me of original issue. I've gone through the tree and done an audit of the device_get_children calls. I think that the issues have been resolved. However, it looks like there's a lot of code in the tree looking for siblings and such. This suggests a close review of the code to pull out common routines into subr_bus might be in order. Each of these hand-rolled routines had slightly different bugs in the error handling...
This reminded me of original issue. I've gone through the tree and done an audit of the device_get_children calls. I think that the issues have been resolved. However, it looks like there's a lot of code in the tree looking for siblings and such. This suggests a close review of the code to pull out common routines into subr_bus might be in order. Each of these hand-rolled routines had slightly different bugs in the error handling...
Mid august mips status update
Just wanted to jot out a quick status update on FreeBSD/mips.
A few weeks ago, diffs were sent out for review. The 6 patches are now down to three. gcc.diff, binutils.diff and pam.diff remain uncommitted.
pam.diff (now pam3.diff) has been receiving feedback from DES and others and is getting close. The first iteration was really far away from being commit quaility, but the last iteration may be the one that goes in.
gcc.diff has received feedback recently. Gonzo and I are in the process of digesting and understanding the feedback. We hope to produce a revised patch shortly, as there are a number of minor issues.
binutils.diff has had no comments. One person volunteered to look at it and commit it, but so far we're still waiting for feedback to make the patch better, or for it to be committed. If we don't hear anything one way or the other, I'll don my flame resistant suit and push it into the tree. There's really no issues with the patch that I can see. What is going to be a challenge is doing the vendor import of a few upstream files. Hopefully the volunteer will pull through and I won't have to learn how to do this in the new svn world. :-)
All the other diffs have been committed to the tree. It was gratifying to get positive feedback on them all, since I was worried more of them would have maintainer timeouts.
You can see the current set of patches in gonzo's patch directory. Grab only the latest pam patch there. The cddl.diff patch should be removed shortly, as I just committed it.
Had I been paying closer attention, I'd have written all this up for the FreeBSD status report.
A few weeks ago, diffs were sent out for review. The 6 patches are now down to three. gcc.diff, binutils.diff and pam.diff remain uncommitted.
pam.diff (now pam3.diff) has been receiving feedback from DES and others and is getting close. The first iteration was really far away from being commit quaility, but the last iteration may be the one that goes in.
gcc.diff has received feedback recently. Gonzo and I are in the process of digesting and understanding the feedback. We hope to produce a revised patch shortly, as there are a number of minor issues.
binutils.diff has had no comments. One person volunteered to look at it and commit it, but so far we're still waiting for feedback to make the patch better, or for it to be committed. If we don't hear anything one way or the other, I'll don my flame resistant suit and push it into the tree. There's really no issues with the patch that I can see. What is going to be a challenge is doing the vendor import of a few upstream files. Hopefully the volunteer will pull through and I won't have to learn how to do this in the new svn world. :-)
All the other diffs have been committed to the tree. It was gratifying to get positive feedback on them all, since I was worried more of them would have maintainer timeouts.
You can see the current set of patches in gonzo's patch directory. Grab only the latest pam patch there. The cddl.diff patch should be removed shortly, as I just committed it.
Had I been paying closer attention, I'd have written all this up for the FreeBSD status report.
20080819
Slimming down the NSLU kernel
A few days ago, I wrote about the NSLU kernel config file being committed to FreeBSD's svn tree. The default compressed kernel is about 1.6MB, but the size of the partition of the NSLU2's flash is 1.25MB, a gap of just under 300kB. With some hacking, I've been able to reduce the size of the kernel to fit.
The default kernel's text+data size is 3,425,844 bytes. Compressed, with the appropriate headers, this drops to 1,591,109 bytes. However, the goal is 1,310,720 bytes. We're short by at least 294,553 bytes of fitting into the kernel portion of the flash on the NSLU.
My first thought was to start cutting things out. I removed IPv6 (options INET6) since I didn't need it for my setup. This saved 210,797 bytes in the uncompressed kernel and 74,115 bytes in the compressed kernel. This one option shaved 5% (compressed) of the kernel size. A move in the right direction, but more was needed.
Next, I recalled from previous attempts that there's many inline functions that don't need to be inlined. There's a small performance gain from inlining these functions, but it can add a lot to the kernel. So I added three options to the kernel config:
At this point I noticed that there were a lot of things in the kernel that weren't required for boot, and that had shown up as being larger. When doing the size reduction, often times I use the 'size' command to get the top 20 .o files to see if there's junk that can just be omitted from the kernel. In this case, I saw that usb, scsi and releated drivers consumed a lot of space. This could be loaded from a number of modules after boot if I was booting from a RAM disk. Since the plan was to put an initrd-like ram disk in the other partition of the flash, I went ahead and removed these pieces:
Another big area of the kernel is the code brought in with 'options miibus' configuration line. This brings in all the phy drivers on the off chance you'll need it. In many embedded systems, you know which phy driver you have, and can wire in only the one or ones you need. Since I wasn't planning on using this box as a general purpose router, that needed to work with any Ethernet dongle that was plugged into the USB port, I went ahead and transitioned to this configuration. The NSLU has a RealTek Phy that needs the rlphy driver. This means that I changed the config file like so:
At the end of all this, the compressed kernel had been reduced from 1,625,125 bytes down to 1,286,193 bytes, for a savings of 320,080 bytes. This was enough margin for me to feel comfortable trying to burn it into my NSLU. Unfortunately, I ran out of time tonight to try it, so the story of that experiment will wait for another post. Also, I don't know how to make blogspot do tables, or I'd have made some nice tables with all this data for this log.
There's likely more options that can be explored to squeeze even more bytes out of the kernel. bzip2 might be a good place to get maybe 10% more space back (at these sizes, an extra 100kB compressed, or 250kB uncompressed). The exploder for bzip2 is bigger and uses more memory.
Looking at the .o files that are laying around that pci.o is kinda big, suggesting that we need to break it up some more. In previous experiments, separating out the MSI and PCIe stuff helped quite a bit. I'm unsure what the best newbusly way to extract this functionality might be, but it could save us 20kB uncompressed (maybe 8k compressed, iirc).
There's a number of other places code is agresively inlined, these could be investigated. there's
a few things in the tree tagged as standard that likely could be made to be options. There's much room here to explore a number of different options to reduce the kernel size even further if the need presents itself.
The nfs server option is about 45kB. Soft updates run about the same. nfsv4 also eats a lot of memory (looks to be 55kB).
However, for all these options, it would be nice is the NAS could have RAID, FAT, ntfs, smbfs and ext2fs support as well. Continuing to trim would allow this more easily. Or at least eliminate the need for loadable modules.
This is to say, there's a lot of areas for further research and documentation. I didn't even look at using a /boot/loader either. Maybe that can be helpful... Maybe I'll turn that into a research paper for one of the conferences... Either the continued size reduction thing, or using /boot/loader.
Finally, I've uploaded the changed NSLU config file in case my verbal descriptions here were insufficient.
The default kernel's text+data size is 3,425,844 bytes. Compressed, with the appropriate headers, this drops to 1,591,109 bytes. However, the goal is 1,310,720 bytes. We're short by at least 294,553 bytes of fitting into the kernel portion of the flash on the NSLU.
My first thought was to start cutting things out. I removed IPv6 (options INET6) since I didn't need it for my setup. This saved 210,797 bytes in the uncompressed kernel and 74,115 bytes in the compressed kernel. This one option shaved 5% (compressed) of the kernel size. A move in the right direction, but more was needed.
Next, I recalled from previous attempts that there's many inline functions that don't need to be inlined. There's a small performance gain from inlining these functions, but it can add a lot to the kernel. So I added three options to the kernel config:
options MUTEX_NOINLINEThis resulted in a size reduction of 432,984 bytes (uncompressed) and 87,289 bytes (compressed). This is also a significant savings, and meant that we'd saved 161,404 bytes in the compressed kernel so far. We were still ~133,000 bytes shy of the mark.
options RWLOCK_NOINLINE
options SX_NOINLINE
At this point I noticed that there were a lot of things in the kernel that weren't required for boot, and that had shown up as being larger. When doing the size reduction, often times I use the 'size' command to get the top 20 .o files to see if there's junk that can just be omitted from the kernel. In this case, I saw that usb, scsi and releated drivers consumed a lot of space. This could be loaded from a number of modules after boot if I was booting from a RAM disk. Since the plan was to put an initrd-like ram disk in the other partition of the flash, I went ahead and removed these pieces:
#device usbThis trimming saved 278,837 bytes (uncompressed) and 133,520 bytes (compressed). This was huge, and brought the total trimmed up to 294,924 bytes. This is just barely over the line, so I thought I'd go for a little more.
#options USB_DEBUG
#device ohci
#device ehci
#device ugen
#device umass
#device scbus # SCSI bus (required for SCSI)
#device da # Direct Access (disks)
Another big area of the kernel is the code brought in with 'options miibus' configuration line. This brings in all the phy drivers on the off chance you'll need it. In many embedded systems, you know which phy driver you have, and can wire in only the one or ones you need. Since I wasn't planning on using this box as a general purpose router, that needed to work with any Ethernet dongle that was plugged into the USB port, I went ahead and transitioned to this configuration. The NSLU has a RealTek Phy that needs the rlphy driver. This means that I changed the config file like so:
#device miibus # NB: required by npeThis option shaved a few more bytes off the total. 80,012 bytes (uncompressed) and 25,156 bytes (compressed).
device mii
device rlphy
At the end of all this, the compressed kernel had been reduced from 1,625,125 bytes down to 1,286,193 bytes, for a savings of 320,080 bytes. This was enough margin for me to feel comfortable trying to burn it into my NSLU. Unfortunately, I ran out of time tonight to try it, so the story of that experiment will wait for another post. Also, I don't know how to make blogspot do tables, or I'd have made some nice tables with all this data for this log.
There's likely more options that can be explored to squeeze even more bytes out of the kernel. bzip2 might be a good place to get maybe 10% more space back (at these sizes, an extra 100kB compressed, or 250kB uncompressed). The exploder for bzip2 is bigger and uses more memory.
Looking at the .o files that are laying around that pci.o is kinda big, suggesting that we need to break it up some more. In previous experiments, separating out the MSI and PCIe stuff helped quite a bit. I'm unsure what the best newbusly way to extract this functionality might be, but it could save us 20kB uncompressed (maybe 8k compressed, iirc).
There's a number of other places code is agresively inlined, these could be investigated. there's
a few things in the tree tagged as standard that likely could be made to be options. There's much room here to explore a number of different options to reduce the kernel size even further if the need presents itself.
The nfs server option is about 45kB. Soft updates run about the same. nfsv4 also eats a lot of memory (looks to be 55kB).
However, for all these options, it would be nice is the NAS could have RAID, FAT, ntfs, smbfs and ext2fs support as well. Continuing to trim would allow this more easily. Or at least eliminate the need for loadable modules.
This is to say, there's a lot of areas for further research and documentation. I didn't even look at using a /boot/loader either. Maybe that can be helpful... Maybe I'll turn that into a research paper for one of the conferences... Either the continued size reduction thing, or using /boot/loader.
Finally, I've uploaded the changed NSLU config file in case my verbal descriptions here were insufficient.
20080816
PCI Bridge hacks
Recently, someone sent me a new ExpressCard. This isn't the first ExpressCard that I've had. However, this one is PCIe based. I plugged it in, and it didn't work. I had no idea where to begin tracking it down, so I've added some information to pcib device. Now, we report the all the bus numbers that are relevant. Turns out after a little more digging the memory allocation on the bridge is wrong. None was allocated by the BIOS and FreeBSD isn't picking up the slack. That's the next set of problems to solve.... After that, I'll look at the hotplug functionality...
20080809
FreeBSD/avr32 spotted in the wild
A very preliminary port to the AVR32 has been spotted in the wild. Arnar Mar Sig posted a dmesg of FreeBSD/avr32. You can find his post through this link.
For those of you unfamiliar with the AVR32 architecture, it is an architecture that is used primarily in embedded applications. AVR may be initials familiar to many readers as microcontrollers. Atmel took its know-how and created a 32-bit version of this architecture basically from scratch.
You can find more information about the processor at atmel's web site, or at wikipedia.
The work here clearly is preliminary, but it is very cool none the less. FreeBSD embedded is on the move...
[[ typos corrected, I hope :-) ]]
For those of you unfamiliar with the AVR32 architecture, it is an architecture that is used primarily in embedded applications. AVR may be initials familiar to many readers as microcontrollers. Atmel took its know-how and created a 32-bit version of this architecture basically from scratch.
You can find more information about the processor at atmel's web site, or at wikipedia.
The work here clearly is preliminary, but it is very cool none the less. FreeBSD embedded is on the move...
[[ typos corrected, I hope :-) ]]
20080807
The dog ate my homework.
People have reacted favorably to a recent commit that I made where I said that my dog chewed up a card so I couldn't test it. I thought people would be interested in seeing this card.
First, the commit message:
You can see the whole commit here if you are into that as well.
Several people remarked this was the first time someone used "The dog ate my homework" excuse in the project. So I thought I'd produce pictures of the card for your enjoyment.
Here's a shot of the top. Notice how one of the teeth punctured the outer shell...
Here's a shot of the bottom. The damage doesn't show up well in the photo, but there's many teeth marks here.
Finally, the force of the chewing popped open the case. Here's a shot of the inside. Notice how the pins to the PCMCIA connector are severed. Otherwise, the card is in great shape...
First, the commit message:
Log:
Convert to new style PC Card front end driver. Add support for the
NEC PC-9801N-J02 and PC-9801N-J02R. I can't test the former because
it requires resources that conflict with my laptop. I can't test the
latter because my dog chewed up my -J02R card and it didn't survive
well enough for me to test.
You can see the whole commit here if you are into that as well.
Several people remarked this was the first time someone used "The dog ate my homework" excuse in the project. So I thought I'd produce pictures of the card for your enjoyment.
Here's a shot of the top. Notice how one of the teeth punctured the outer shell...
Here's a shot of the bottom. The damage doesn't show up well in the photo, but there's many teeth marks here.
Finally, the force of the chewing popped open the case. Here's a shot of the inside. Notice how the pins to the PCMCIA connector are severed. Otherwise, the card is in great shape...
20080806
Minor PC Card work
I have a large collection of PC Cards. Well over 100, maybe over 200 cards. These cards are my test bed for the FreeBSD PC Card (both 16-bit and 32-bit) software that I maintain. Sometimes, I take cards out of the boxes at random at times and try them. Other times, I'll take all the cards that are affected by a certain driver change and test them. When I did that recently, I found a hole in the PC Card system.
This hole is very minor. There's no way for a driver to select the configuration entry that is used for the card. Usually, this doesn't matter one bit at all. Drivers work perfectly fine with the configuration that's automatically selected for cards. The PC Card spec has evolved over the years to the point where it is all automated. Certainly for 32-bit cards, but also for most 16-bit cards, even multifunction ones.
However, there's some older cards, some of them interesting to me, that need some special hand holding. These cards perform better with different entries, or activate both the ethernet and the modem on the card, instead of just the modem, when a different entry is selected. Trouble was, there was no way to do this in FreeBSD easily.
I just committed some changes to the PC Card system that will allow 16-bit PC Cards to select the configuration entry entry they will use. There are some restrictions. First, it can only be done in the probe routine for the driver. Second, the driver's probe routine must return 0. Big problems happen if the card is merely 'bidding' on a device and tries to set the right configuration. This may seem harsh, until you realize that if a probe routine knows enough about the card to try to set a configuration entry, then it isn't a generic driver anymore.
Also, as a nice side effect of this work, I've made things more robust for people that insert a card, only to discover that they didn't have the driver for it loaded. There used to be many sharp edges in this code that could cause resource leaks when just the right sequences of load/unload of drivers and removal and insertion of the cards happened. Now, it is all done in one routine, so things should be more robust. Please contact me if I somehow messed that up.
So this is one more ripple effect of the IF_NEEDSGIANT removal patches. I never would have looked at this stuff had I not been testing patches for John Baldwin. It is interesting the sorts of trails one finds oneself down when trying to help others out, as well as test some hardware that would otherwise be laying around.
This hole is very minor. There's no way for a driver to select the configuration entry that is used for the card. Usually, this doesn't matter one bit at all. Drivers work perfectly fine with the configuration that's automatically selected for cards. The PC Card spec has evolved over the years to the point where it is all automated. Certainly for 32-bit cards, but also for most 16-bit cards, even multifunction ones.
However, there's some older cards, some of them interesting to me, that need some special hand holding. These cards perform better with different entries, or activate both the ethernet and the modem on the card, instead of just the modem, when a different entry is selected. Trouble was, there was no way to do this in FreeBSD easily.
I just committed some changes to the PC Card system that will allow 16-bit PC Cards to select the configuration entry entry they will use. There are some restrictions. First, it can only be done in the probe routine for the driver. Second, the driver's probe routine must return 0. Big problems happen if the card is merely 'bidding' on a device and tries to set the right configuration. This may seem harsh, until you realize that if a probe routine knows enough about the card to try to set a configuration entry, then it isn't a generic driver anymore.
Also, as a nice side effect of this work, I've made things more robust for people that insert a card, only to discover that they didn't have the driver for it loaded. There used to be many sharp edges in this code that could cause resource leaks when just the right sequences of load/unload of drivers and removal and insertion of the cards happened. Now, it is all done in one routine, so things should be more robust. Please contact me if I somehow messed that up.
So this is one more ripple effect of the IF_NEEDSGIANT removal patches. I never would have looked at this stuff had I not been testing patches for John Baldwin. It is interesting the sorts of trails one finds oneself down when trying to help others out, as well as test some hardware that would otherwise be laying around.
20080803
NSLU2 support committed to FreeBSD/arm
I just committed the basic Linksys NSLU2 support to the subversion tree. It boots and runs on an NFS root. We're currently lacking support for the leds, the buttons and the on-board flash. Here's some basic instructions if you want to try it on your NSLU2. They are adapted from Sam Leffler's README file for the AVILA, which is adapted from other sources, including Olivier Houchard's and my instructions that have appeared.
Build world
The FreeBSD handbook can help you find the sources, etc Once you have them, and they are from -CURRENT after 8am on 2008-08-03, you can proceed to build the world. Each section is cumulative from the previous section for simplicity sake.
Setup NFS root
Find a server that has some disk space. You'll need about 250MB of space for a full FreeBSD image.
Setup diskless system
diskless(8) gives a good overview in how to do this. It is left as an exercise for the read to come up with all the settings. Usually /etc/rc.conf and /etc/fstab must be configured. /etc/ttys is another one that usually needs some tlc. If there's enough demand, I'll write about this in the future.
Build and install the kernel
Note: the NSLU kernel is configured with the root filesystem mounted via NFS over the npe0 wired interface.
You should now have an NFS-mountable root filesystem with a kernel. The final step is to setup network diskless booting from the board. It is assumed you have a DHCP server operating on your network and the server is configured to supply the necessary information in the DHCP lease. If you run the ISC DHCP server the following configuration information is an example of how to do this:
Note: the root-opts item specifies the root filesystem should be mounted with the nolocked option; this just short-circuits file locking requests so you don't get complaints from programs that use the pidfile(3) routine (e.g. devd)
Install kernel in tftp area
Place the kernel in the TFTP area for booting from the prom monitor. If your TFTP server returns file from /tftpboot (default) then do something like:
Boot using Redboot
dmesg
Here's a complete transcript of my doing this. The .gz file listed below really isn't the simple gz file, but rather kernel.gz.tramp from the kernel build. Also, I've hacked my NSLU to have a serial port, which make development like this easier. See the web for instructions on how to do a no-mod breakin.
- Build world
- Setup NFS root
- Configure diskless system
- Build and Install Kernel
- Put Kernel in tftp area
- Boot from redboot
Build world
The FreeBSD handbook can help you find the sources, etc Once you have them, and they are from -CURRENT after 8am on 2008-08-03, you can proceed to build the world. Each section is cumulative from the previous section for simplicity sake.
setenv TARGET arm
setenv MAKEOBJDIRPREFIX /tmp/$USER/obj
setenv TARGET_BIG_ENDIAN t
setenv TARGET_CPU_TYPE xscale
make buildworld
Setup NFS root
Find a server that has some disk space. You'll need about 250MB of space for a full FreeBSD image.
setenv ROOT /data/freebsd/roots/slug
make installworld DESTDIR=$ROOT
mergemaster -m $SRC/etc -D $ROOT -i -A arm
Setup diskless system
diskless(8) gives a good overview in how to do this. It is left as an exercise for the read to come up with all the settings. Usually /etc/rc.conf and /etc/fstab must be configured. /etc/ttys is another one that usually needs some tlc. If there's enough demand, I'll write about this in the future.
Build and install the kernel
make KERNCONF=NSLU buildkernel
make KERNCONF=NSLU DESTDIR=$ROOT installkernel
Note: the NSLU kernel is configured with the root filesystem mounted via NFS over the npe0 wired interface.
You should now have an NFS-mountable root filesystem with a kernel. The final step is to setup network diskless booting from the board. It is assumed you have a DHCP server operating on your network and the server is configured to supply the necessary information in the DHCP lease. If you run the ISC DHCP server the following configuration information is an example of how to do this:
option root-opts code 130 = string; # NFS / mount options
host slug {
hardware ethernet 00:d0:12:02:47:68;
fixed-address 10.0.0.221;
next-server 10.0.0.251;
filename "kernel-slug.nfs";
option root-path "10.0.0.251:/data/freebsd/roots/slug";
option root-opts "nolockd";
}
Note: the root-opts item specifies the root filesystem should be mounted with the nolocked option; this just short-circuits file locking requests so you don't get complaints from programs that use the pidfile(3) routine (e.g. devd)
Install kernel in tftp area
Place the kernel in the TFTP area for booting from the prom monitor. If your TFTP server returns file from /tftpboot (default) then do something like:
cp $ROOT/boot/kernel/kernel /tftpboot/kernel-slug.nfs
Boot using Redboot
+(hit control C here)
RedBoot> ip -h 10.0.0.251 -l 10.0.0.1
IP: 10.0.0.1/255.255.255.0 Gateway: 0.0.0.0
Default server: 10.0.0.251
RedBoot> load -b 0x200000 kernel-avila.nfs
Using default protocol (TFTP)
Address offset = 0x40000000
Entry point: 0x00200100, address range: 0x00200000-0x004db2d4
RedBoot> go
dmesg
Here's a complete transcript of my doing this. The .gz file listed below really isn't the simple gz file, but rather kernel.gz.tramp from the kernel build. Also, I've hacked my NSLU to have a serial port, which make development like this easier. See the web for instructions on how to do a no-mod breakin.
+Ethernet eth0: MAC address 00:14:bf:68:47:ba
IP: 192.168.0.1/255.255.255.0, Gateway: 192.168.0.1
Default server: 0.0.0.0, DNS server IP: 0.0.0.0
RedBoot(tm) bootstrap and debug environment [ROMRAM]
Red Hat certified release, version 1.92 - built 15:16:07, Feb 3 2004
Platform: IXDP425 Development Platform (XScale)
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.
RAM: 0x00000000-0x02000000, 0x000723a0-0x01ff3000 available
FLASH: 0x50000000 - 0x50800000, 64 blocks of 0x00020000 bytes each.
== Executing boot script in 2.000 seconds - enter ^C to abort
^C
RedBoot> ip -l 10.0.0.12 -h 10.0.0.8
IP: 10.0.0.12/255.255.255.0, Gateway: 192.168.0.1
Default server: 10.0.0.8, DNS server IP: 0.0.0.0
RedBoot> load -b 0x200000 kernel.nslu.gz
Using default protocol (TFTP)
Address offset = 0xf0000000
Entry point: 0x00200074, address range: 0x00200000-0x003830fc
RedBoot> go
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2008 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 8.0-CURRENT #12: Sun Aug 3 00:09:07 MDT 2008
imp@lighthouse:/tmp/imp/obj/arm/cache/svn/head/sys/NSLU
CPU: IXP425 266MHz rev 1 (ARMv5TE) (XScale core)
DC enabled IC enabled WB enabled LABT branch prediction enabled
32KB/32B 32-way Instruction cache
32KB/32B 32-way write-back-locking Data cache
real memory = 33554432 (32 MB)
avail memory = 25894912 (24 MB)
ixp0:on motherboard
pcib0:on ixp0
pci0:on pcib0
ohci0:irq 28 at device 1.0 on pci0
ohci0: [GIANT-LOCKED]
ohci0: [ITHREAD]
usb0: OHCI version 1.0
usb0:on ohci0
usb0: USB revision 1.0
usbd_get_string: getting lang failed, using 0
uhub0:on usb0
uhub0: 3 ports with 3 removable, self powered
ohci1:irq 27 at device 1.1 on pci0
ohci1: [GIANT-LOCKED]
ohci1: [ITHREAD]
usb1: OHCI version 1.0
usb1:on ohci1
usb1: USB revision 1.0
usbd_get_string: getting lang failed, using 0
uhub1:on usb1
uhub1: 2 ports with 2 removable, self powered
ehci0:irq 26 at device 1.2 on pci0
ehci0: [GIANT-LOCKED]
ehci0: [ITHREAD]
usb2: EHCI version 1.0
usb2: companion controllers, 3 ports each: usb0 usb1
usb2:on ehci0
usb2: USB revision 2.0
uhub2:on usb2
uhub2: 5 ports with 5 removable, self powered
ixpclk0:on ixp0
ixpiic0:on ixp0
iicbb0:on ixpiic0
iicbus0:on iicbb0 master-only
iicbus0:at addr 0
iic0:on iicbus0
ixpwdog0:on ixp0
uart0:on ixp0
uart0: [FILTER]
uart0: console (115200,n,8,1)
uart1:on ixp0
uart1: [FILTER]
ixpqmgr0:on ixp0
ixpqmgr0: [ITHREAD]
npe0:on ixp0
npe0: [ITHREAD]
npe0: remember to fix rx q setup
miibus0:on npe0
rlphy0:PHY 1 on miibus0
rlphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
npe0: Ethernet address: 00:14:bf:68:47:ba
npe1:on ixp0
npe1: [ITHREAD]
npe1: remember to fix rx q setup
npe1: Cannot find my PHY.
device_attach: npe1 attach returned 6
ixpclk0: [FILTER]
Timecounter "IXP425 Timer" frequency 66666600 Hz quality 1000
Timecounters tick every 10.000 msec
bootpc_init: wired to interface 'npe0'
Sending DHCP Discover packet from interface npe0 (00:14:bf:68:47:ba)
npe0: link state changed to UP
Received DHCP Offer packet on npe0 from 0.0.0.0 (accepted) (no root path)
Sending DHCP Request packet from interface npe0 (00:14:bf:68:47:ba)
Received DHCP Ack packet on npe0 from 0.0.0.0 (accepted) (got root path)
npe0 at 10.0.0.12 server 0.0.0.0 boot file kernel.slug
subnet mask 255.255.255.0 router 10.0.0.1 rootfs 10.0.0.8:/pe/slug rootopts nolockd
Adjusted interface npe0
Trying to mount root from nfs:
NFS ROOT: 10.0.0.8:/pe/slug
warning: no time-of-day clock registered, system time will not be set accurately
warning: no time-of-day clock registered, system time will not be set accurately
Interface npe0 IP-Address 10.0.0.12 Broadcast 10.0.0.255
Loading configuration files.
No suitable dump device was found.
Entropy harvesting: interrupts ethernet point_to_point kickstart.
Starting file system checks:
mount_nfs: can't update /var/db/mounttab for 10.0.0.8:/pe/slug
Setting hostuuid: 1c728616-1dd2-11b2-9fa6-0014bf6847ba.
Setting hostid: 0xb1c1273a.
Mounting local file systems:.
Setting hostname: slug.
net.inet6.ip6.auto_linklocal: 1 -> 0
DHCPREQUEST on npe0 to 255.255.255.255 port 67
ip length 328 disagrees with bytes received 332.
accepting packet with data after udp payload.
DHCPACK from 10.0.0.1
bound to 10.0.0.12 -- renewal in 900 seconds.
lo0: flags=8049metric 0 mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
npe0: flags=8843metric 0 mtu 1500
ether 00:14:bf:68:47:ba
inet6 fe80::214:bfff:fe68:47ba%npe0 prefixlen 64 scopeid 0x1
inet 10.0.0.12 netmask 0xffffff00 broadcast 10.0.0.255
media: Ethernet autoselect (100baseTX)
status: active
Additional routing options:.
Starting devd.
Additional IP options:.
Mounting NFS file systems:.
Creating and/or trimming log files:.
Starting syslogd.
/etc/rc: WARNING: Dump device does not exist. Savecore not run.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
Initial arm initialization:.
Additional ABI support:.
Clearing /tmp (X related).
Starting local daemons:.
Updating motd.
Mounting late file systems:.
Starting cron.
Local package initialization:.
Starting inetd.
Starting background file system checks in 60 seconds.
Thu Jan 1 00:00:39 UTC 1970
FreeBSD/arm (slug) (ttyu0)
login: root
Jan 1 00:03:24 slug login: ROOT LOGIN (root) ON ttyu0
Last login: Thu Jan 1 00:42:28 on ttyu0
Copyright (c) 1992-2008 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 8.0-CURRENT (NSLU) #12: Sun Aug 3 00:09:07 MDT 2008
Welcome to FreeBSD!
Before seeking technical support, please use the following resources:
o Security advisories and updated errata information for all releases are
at http://www.FreeBSD.org/releases/ - always consult the ERRATA section
for your release first as it's updated frequently.
o The Handbook and FAQ documents are at http://www.FreeBSD.org/ and,
along with the mailing lists, can be searched by going to
http://www.FreeBSD.org/search/. If the doc distribution has
been installed, they're also available formatted in /usr/share/doc.
If you still have a question or problem, please take the output of
`uname -a', along with any relevant error messages, and email it
as a question to the questions@FreeBSD.org mailing list. If you are
unfamiliar with FreeBSD's directory layout, please refer to the hier(7)
manual page. If you are not familiar with manual pages, type `man man'.
You may also use sysinstall(8) to re-enter the installation and
configuration utility. Edit /etc/motd to change this login announcement.
nslug# ntpdate harmony
3 Aug 07:04:18 ntpdate[582]: step time server 10.0.0.6 offset 1217746845.716155 sec
slug# date
Sun Aug 3 07:04:19 UTC 2008
slug# df
Filesystem 1K-blocks Used Avail Capacity Mounted on
10.0.0.8:/pe/slug 55871592 49741636 1660230 97% /
devfs 1 1 0 100% /dev
10.0.0.8:/pe 55871592 49741636 1660230 97% /pe
20080801
When worlds collide
Recently, I had to check out a linux tree at work from cvs. I only knew the repository, but didn't know the module to check out. So I made my best guess and started building the kernel. After plowing through a couple of little things, I hit the wall with:
scripts/Makefile.build:17: /pe/imp/xxx/linux-2.6.xxx/net/core/Makefile: No such file or directory
gmake[2]: *** No rule to make target `/pe/imp/xxx/linux-2.6.xxx/net/core/Makefile'. Stop.
Guess what someone forgot to do when they were doing the cvs import :-)
scripts/Makefile.build:17: /pe/imp/xxx/linux-2.6.xxx/net/core/Makefile: No such file or directory
gmake[2]: *** No rule to make target `/pe/imp/xxx/linux-2.6.xxx/net/core/Makefile'. Stop.
Guess what someone forgot to do when they were doing the cvs import :-)