One problem solved, another remains

Well, my third eTrex arrived today, a nice new one and so far it seems fine - despite the abysmal weather I took a stroll to try it out. I'm still puzzling over exactly where the Bleaklow fence line goes between Shining Clough and Woodhead, so I parked up above Woodhead tunnel and walked up onto the Trans Pennine Trail (the old turnpike road) then wandered westwards towards Woodhead Bridge. That gave me a chance to reccie the other side of the valley and figure out where the fence goes. It appears to come down to the Longdendale trail along Smithy Clough, but I've still no clear idea of where it goes between Stable Clough and Shining Clough. One of the nice things with the Summit is you can use it for doing resections - because it has a built-in compass you can mark your current position, then take a bearing from where you are and project another waypoint along it. If you do this three times from different vantage points and join up the three resulting lines (dead easy in OziExplorer - just set up three two-waypoint routes and display them),you get the traditional 'cocked hat' that shows you where the point of interest is.

As I said in my original post, I'd also paid £20.00 to Geomantics for some cleaned-up SRTM height data for OziExplorer. Well, it eventually arrived - in a format that's completely incompatible with OziExplorer, despite the website clearly saying " We supply geo-edited SRTM data in a suitable format ... for use with 3rd party programs such as Bryce, Terragen, OziExplorer, 3D Studio, Photoshop etc." Bollocks. It's supplied as 5km squares of 16-bit raw height data, and OziExplorer doesn't understand that format at all. Eventually, after repeated requests for information, Geomantics told me I had to download a 3d terrain modelling application, and a plugin, and re-reference and convert all the data - and I have 74 files worth, although I don't want it all. You'd need to have quite an in-depth knowledge of GIS and earth coordinate systems to be able to do this, which leaves me out. Needless to say, I've emailed them and the electronic payment service they use to ask for my money back, it will be interesting to see if I get it. I've also suggested that they remove the frankly untrue claim that the data can be used with OziExplorer from their website - if you get here via google and are intending to buy their data for use with OziExplorer, take my advice and don't.

Categories : Peak District, Tech

Garmin Customer Support - the saga continues

Yesterday the nice chap at GPS4Less phoned me up to let me know that Garmin were going to send me a brand new, tested unit and it would be arriving by courier today. Seemingly the fact that I'd mailed a link to my previous post to both the CEO and Director of Sales and Marketing of Garmin had achieved the desired effect. I had an email from Garmin's European Service/Support Manager apologising for the problems I'd had, and saying:

Our current turn around time is 3 days, and in a case like this we would replace your unit with a new boxed product. I am sorry that this was not conveyed to you following your first contact with us. We are now addressing the calculation of our turn around time claims.

So it seems that Garmin not only have the things in stock, but the original 1-2 weeks estimate for getting it replaced wasn't right either. Sure enough, at about 2:30 this afternoon the replacement was delivered. They'd included a nice case and a couple of spare sets of batteries, along with a letter. I powered the Summit up, only to discover that the LCD display was dodgy - pixels were 'bleeding' left and right across the screen from the edges of the various dialog boxes and icons. I know that LCDs are prone to this, but it was really quite noticeable, and on the previous unit - despite it's other fault - there wasn't any sign of it at all. Just to confirm I wasn't imagining it I nipped down to the Ranger station to compare it with Fiona's identical model. Despite hers being several years old and having had a hard life, the display was much better than mine.

I'd phoned the Garmin Service Manager up to explain the problem with the replacement before I went to compare my Summit to Fiona's, so when I got back I phoned him back up to arrange for yet another unit to be sent to me tomorrow. As I was digging through the contents of the box they'd sent me, I noticed a slip titled Newly overhauled 1-year limited warrany certificate, so whilst I was on the phone I asked if that meant that I'd been supplied with a repaired unit to replace my original brand-new unit. "Yes, although you were supposed to be supplied with a new one" was the reply. I'm sure that was his original intention when he mailed me yesterday (see above), but obviously something had got lost in the translation - which isn't very impressive - but hardly surprising in light of my experiences with them so far. Expecting me to pay £150.00 for a broken-and-repaired, second-hand Summit doesn't exactly seem reasonable, which he accepted. My third-and-hopeully-final Summit will be arriving tomorrow, just in time for my birthday, which is what the bloody thing was supposed to be for anyway.


Tags : , , ,
Categories : Tech

eTrex Summit less than the acme

Well, my brand-new eTrex Summit is having to be replaced - it has an unfortunate tendency to turn itself off for no apparent reason, even with a fresh set of batteries. There's no low battery warning, it just switches off. It did this at least ten times on Saturday when I was using it, and despite re-flashing the firmware and doing a factory reset, it still continues to do the same thing at unpredictable intervals. I suspect that it's something to do with the compass / GPS switchover - at a configurable speed it switches over to the inbuilt compass for heading information, and from what I can tell sometimes when it switches to compass it also switches off completely. I got in touch with GPS4Less who I bought it from, and they don't have any more left, and from what they are telling me neither do Garmin - seemingly Garmin have an abysmal inventory control system, and stuff can take 5-8 weeks to come into stock. I spoke to Garmin UK myself and they said it could take up to a couple of weeks to get a replacement to me, and they point blank refused to tell me if they had them in stock for 'security reasons'! The guy I spoke to at GPS4Less is going to see if he can locate me a replacement from somewhere, but I'm pretty annoyed at Garmin - firstly the unit is faulty, secondly they won't tell me if they actually have any of the damn things in the UK and thirdly it seems that even if they do have them it's going to take an unacceptable amount of time to get a replacement to me.

0 out of 10 for customer service, Garmin.


I posted the URL of this entry into Garmin's customer support webpage and also asked them how long it would take to get a replacement, and surprise, surprise, within 15 minutes I had a reply:

Dear Alan.

Thank you for contacting Garmin Europe Support.

Please return your unit to the address below, with an accompanying letter giving full details of the fault:

Garmin (Europe) Ltd
Unit 5
The Quadrangle
Abbey Park
SO51 9DL

If the unit is in warranty please enclose a copy of the receipt

If you have any further queries please don't hesitate to contact us again

This is pretty obviously a boilerplate reply, and it didn't actually tell me anything I couldn't get from their website. It also didn't answer my main question regarding how long it would take to get a replacement. I replied:

I contacted Garmin UK by phone today and was told it would take up to two weeks to get the unit back to me, is this correct? The unit is brand new - I only got it last Wednesday. It would be reasonable to have to wait two weeks if the unit was several months old and was being repaired under warranty, but it isn't - it was DOA. I don't want it repaired, I would like a new one. And being told rather brusquely on the phone that you couldn't even tell me if you had any in stock wasn't exactly helpful either.

And got the following brush-off:

Dear Alan.

Thank you for contacting Garmin Europe Support.

If the unit is new please return to the shop for replacement.

If you have any further queries please don't hesitate to contact us again

I didn't consider this to be an acceptable answer either - basically 'Go away we don't want to know' seemed to be the gist, so I asked again:

The shop in question doesn't have any more in stock, and have been unable to find out from you (Garmin) if/when you will be able to supply them with any more units. To repeat my original question, do or do you not have any available in the UK, and if so how long will it take to get one to me?

And by now I suspect you can probably guess what the reply looked like:

Dear Alan.

Thank you for contacting Garmin Europe Support.

Unfortunately this is proprietary information. Please see your dealer for availability of products.

The only options that you have is send it to the dealer or send it to us.

If you have any further queries please don't hesitate to contact us again

So it's apparent that Garmin think the answer to the simple question 'Have you a replacement eTrex Summit in the UK that you can ship to me?' is a trade secret that must be protected at all costs - the mind boggles. On that basis I can only assume that anyone who dares to ask for pricing information can expect the Black Helicopters to appear shortly thereafter.

As I've already said, GPS4Less (who have been very helpful) don't have any in stock, and don't know when Garmin will be able to supply them with a replacement, as Garmin are telling them that they themselves don't have any and don't know when they will be getting more - so I'm now back at square one. I've posted the failed unit back to GPS4Less as it's no use to me, so I'm now £149.95 out of pocket, I've had to pay £4.05 to send the unit back (and I bet I don't get that back), and I still don't have a resolution to my question to Garmin, let alone a working GPS. I'm trying to remember when I last received such poor customer service, and I'm struggling - all in all a pretty appalling experience, and it's badly dented my faith in a company that I previously held in high regard.

Garmin, your customer service sucks.

Tags : , , ,
Categories : Tech

A new toy - Garmin eTrex Summit

Garmin eTrex SummitMy latest toy arrived yesterday - a Garmin eTrex Summit GPS. I already have a Garmin 12XL, and although it's an excellent GPS it is a little bulky, and it eats batteries four at a time. As my birthday is coming up, I decided to treat myself to a newer model - Fiona has a eTrex Summit that I'd played with, and I particularly liked the fact that it had an altimeter and a flux-gate electronic compass - very Stargate SG1. The last time I looked for a GPS with a compass built in, the only one that was available was the Silva model, and that cost £ bazillions.

I originally thought about getting one from eBay - what an utter waste of time that was. The Summit retails for about £150, including VAT + P&P, so I thought I might be able to pick one up for about $100-£120 on eBay. Wrong! I bid on two, and on both the price quickly soared above my £112 bid limit. I have no idea why someone would pay £140 + P&P on eBay for something that they could get from a retail outlet for £150. Gary helpfully explained it to me - "They are all stupid", and I think he's probably right. I'm going to put my old 12XL up for sale on eBay - they retail for about £150, so I'm hoping for something in excess of £200.

Mostly I like the eTrex Summit - the smaller size, lightness, half the batteries, a better display, and of course the altimeter and compass. The unit will also hold more waypoints, routes now have a realistic number of points in them, it can can hold multiple track logs - all these things are a definite plus. There are some downsides compared to the 12XL however. Firstly there's no 'Average position' function to increase the accuracy when saving a new waypoint. Secondly it doesn't store waypoint comments - on most of the Garmin consumer units the waypoint names are restricted to just 6 characters, which leads to some very cryptic abbreviations. The 12XL allowed you to store a longer description with the waypoint so that you could check you'd picked the right one - this is missing on the Summit. The third and probably most serious criticism is that once you've stored a waypoint there appears to be no way to update it to your current position. If you've entered a waypoint off a map it may not be 100% accurate or if you marked it in the field you may not have had a particularly good satellite fix, so it's been my practice with the 12XL to update waypoints as I visited them. With the Summit it appears the only way to do this is to delete and re-save the waypoint, which is a pain to say the least. I can't believe Garmin really haven't provided a way to do this, but I can't find anything in either the manual or on the web. Shame.

Another nit is that Garmin changed the connector used for the upload/download cable, so the old one I made for the 12XL no longer fits. The official Garmin cables retail for about £30, and last time round I made my own because of the price, using a connector supplied by someone I found on the web. This time round I bought a ready-made cable for only £12.95 inc VAT + P&P from the most excellent Lynks Cables. I ordered this mid-afternoon and it arrived on my doormat the following morning. They operate on a trust system as far as payment goes - they dispatch the goods and you can either keep them and pay for them or send them back. They offer a wide range of cables for all sorts of applications, and the one I received was a professionally-made cable complete with moulded connectors and a RF choke.

With the aid of the cable it was the work of moments to copy all of my 230+ existing Dark Peak waypoints from the 12XL onto the Summit, using OziExplorer. However - another nit - Garmin have extended the waypoint symbol set in the Summit, and even though some of the symbols are the same on both the 12XL and Summit they have been renumbered so all the symbols end up muddled. Bah. OziExplorer is an excellent software package which allows you to overlay waypoints, routes and track logs on a map (and much, much more besides), so you can manage all the information in your GPS graphically - I consider it to be an indispendable adjunct to my GPS. I've had a copy for 6 years and I've been very happy with it. When I updated it recently I noticed there was a 3-D add-on available. I didn't expect much, but I downloaded it and the free NASA SRTM height data - and I was blown away, it really does make the map match the terrain - I had endless hours of fun plotting places I knew well in 3-D and comparing it to my memory . You can also overlay your GPS data on the rendered map surface. It's still a beta product so it has a few quirks, but I'm very impressed and for less than £18? Amazing. I've subsequently coughed up £20 for some georeferenced and cleaned up SRTM data from Geomantics as some of the features on the raw SRTM data don't align exactly with the map.

Anyway, I will be out on Saturday mapping the next segment of the Bleaklow fence, so I'll get a chance to test out my new toy in earnest.

Categories : Peak District, Tech

The Countryside Rights Of Way Act isn't just about footpaths

I noticed this interesting item on the BBC news website. Seemingly the number of egg thefts from bird's nests is at an all-time low, and as the report says:

There is no doubt that the sharp decrease in the number of nest robberies is because seven egg collectors have gone to prison since the Countryside and Rights of Way Act 2000 allowed judges and magistrates to impose custodial sentences in England and Wales, instead of just fines.

When we were given our CROW training prior to the introduction of the act we were told that the act was even more important in terms of its wildlife impact than it was for its access implications. However the BBC report isn't entirely good news, it also says that there were 143 cases of shooting and destruction of birds of prey and 91 cases of illegal poisoning. I'm afraid they will largely come down to the landowning and "countryside sports" fraternities - their efforts to portray themselves as the cuddly guardians of the countryside often masks a darker side to their activities. As the report referred to in the BBC article says,

Despite dialogue with landowning and fieldsports bodies, publicity and prosecution, the level of persecution has remained constant ... An examination of prosecutions for offences relating to the persecution of birds of prey (including shooting, trapping and poisoning) between 1985 and 2003 indicates that the majority of cases involve individuals with game rearing interests, predominantly gamekeepers ... We remain concerned that the widespread killing of birds of prey, especially on upland moorlands that are managed for grouse shooting, limits the population and distribution of several species.

Most of the incidents seem to have been in Scotland, although there are two reports of Hen Harriers being persecuted in Derbyshire and also two reports of Buzzards being persecuted. I've seen Buzzards around Bleaklow on several occasions now, I hope they don't become a target.

Labrador Tea

Yesterday I set about the second leg of the Bleaklow fence mapping. Bob and I drove to Crowden Station car park, then drove back to Torside visitor centre and left the other car there. There was a Endurance GB horse ride taking place, so the car park was absolutely chock-full with horseboxes and appropriately horsey towing vehicles. We walked back down the Longdendale trail to Reaps, then up the Pennine Way along Torside Clough to where I finished off last week. We followed the fenceline across Sykes Moor towards Torside Naze before turning north-east to head up to Wildboar Clough. The first segment of the fence was new, but as we crossed Torside Grain it reused the existing fenceline.

Fence erosion

As you can see, the bottom of the wire is now about 18 inches above the surface of the ground, and there's a nice line of sheep tracks plus a wrapping of wool around the bottom strand that shows how the sheep have been getting through the fence. This is a bit of a problem, as the whole point of the fence is to keep the sheep out! It also graphically illustrates the severity of the erosion that the Moors for the Future project is trying to combat - this fence is probably not more than 20 years old, and when it was put up the wire would have been level with the surface of the peat. As we headed along the side of the valley below White Mare, we came across another problem that affects the fence, people with pliers:

Cut fence

I have no idea why anybody should feel it is necessary to cut a fence right next to a stile. I assume the people coming up this particular track know and appreciate Bleaklow as it isn't a well-know route, which makes it ironic that they are deliberately damaging something that is there to protect the very environment they have come to enjoy. There were obvious signs of sheep using the cut, plus two ewes inside the fence line - and if there are two there are doubtless more. Last week I found the fence has also been cut near Ferny Hole, in that case next to a stile with a dog gate so it can't even have been to make it possible for a dog to get through. The new fence is all topped with plain rather than barbed wire as it's intended to keep stock rather than people out, so there really isn't much excuse for cutting it as it's easy enough to climb over if there isn't a convenient stile. Around the eastern margin of the fence there are small signs at regular intervals explaining what it is there for, perhaps we need some along this stretch as well. However, deliberate damage, whilst regrettable is not the most important problem, the fence is more-or-less hopeless for keeping stock out, we counted over 20 points in less than 1km where sheep had been getting through.

Fence erosion

As we were climbing up Wildboar we saw a Buzzard. These seem to be increasingly common, apparently we now have a few breeding pairs in the area, whereas 10 years ago there were none. About half way up Wildboar both Bob and I smelt smoke - something that always makes me nervous after last year's conflagration. We got on the radio to ask if there were any controlled burns planned, but as we couldn't see any smoke it was impossible to say where the fire was actually coming from.

According to the outline map of the fence in the office, the fenceline climbs up the SW side of Wildboar Clough for about 750m before heading back towards Rollick stones in a narrow V. Unfortunately, that's completely wrong - we followed the fence for 3km, all the way up Wildboar to Far Moss then across to Black Cough where it finished. This is the old fence that is due for removal so it needed mapping anyway, but it does leave the question of where the fenceline actually goes! Once we got to the end of the fence we started to head back down Black Clough, and on the way Bob offered to show me the Labrador Tea bush (Ledum groenlandicum) that grows to the west of Black Clough.

Labrador Tea Labrador Tea
These plants are related to Rhododendrons, and in fact are native to North America and Canada. This particular one is about the largest I have seen. The leaves have distinctive curled edges, and are covered in red hairs underneath. In summer they have while flowers.

There are about 6-8 of these plants scattered across the Dark Peak and nobody is quite sure how they got here, the best guess is they are garden escapees with the seed being transported by birds. Whilst we were looking for the Labrador Tea I spotted the source of the smoke we had smelled some time earlier, near Shepherds Meeting Stones some 6km downwind of where we had first detected it. A quick call to Fiona confirmed that it was a controlled burn, so we carried on over to Stable Clough and off past The Lodge. The area at the bottom of Stable Clough had always been out of access until the CROW Act came into force last month, and to get to Stable Clough it was always necessary to plough through a bog, along the line of a barbed wire fence. You are now allowed to carry on down the track towards the house, so Bob and I spent some time figuring out the best route across the now-acessible land before heading to the car at Crowden Station and thence back to base.

Hacking loadable kernel modules with perl

I was reading Alan Coopersmith's blog entry on how he hacked the Xserver with the aid of perl, and that reminded me of a hack I did myself a while back, using perl.

Here's the scenario: I work mainly from home, using a Solaris 10 machine running a debug kernel and VPN to connect to work. The VPN connection requires the use of a loadable STREAMS driver supplied by Cisco. I also run Gnome, but one shortcoming of gnome-term is it doesn't support /dev/console. To get around this I have a single dtterm started with the command-line dtterm -C -map -title Console, which means that any console output is captured by the dtterm. Normally it's iconified, but the -map flag means that if anything is output to /dev/console it de-iconifies so I can see the message.

Here's the rub: If you run a debug kernel you get a kernel thread that periodically tries to unload any loadable kernel modules. This is to flush out any problems with modules that don't load and unload properly, for example by leaking memory. The Cisco VPN module locks itself into memory (which is sort of OK), but every time it gets an unload request it logs the fact with the following cmn_err() message which ends up on /dev/console, which definitely isn't OK.

Oct  6 18:18:06 myhost vpnmod: VPN Module 5.2.4 Unload BUSY (Wed Mar 13 00:31:06 MST 2002)

Every time this happens my /dev/console dtterm de-iconifies and I end up playing whack-a-mole.

OK, let's nail that sucker. It's complicated by the fact that we don't have source for the Cisco VPN module, but who's Operating System it it anyway, right? ;-) First, let's find the culprit:

# modinfo | grep vpn
100 7b600000  1f650   -   1  vpnmod (VPN module)
# ifconfig bge0 modlist
0 arp
1 ip
2 vpnmod
3 bge
# find /kernel -name vpnmod
# cp /kernel/strmod/sparcv9/vpnmod vpnmod.sparc.64
# elfdump -s vpnmod.sparc.64 | egrep 'cmn_err|print'
     [178]  0x000000000000 0x000000000000  NOTY GLOB  D    0 UNDEF       vsprintf
     [193]  0x000000000000 0x000000000000  NOTY GLOB  D    0 UNDEF       vcmn_err
     [255]  0x000000000000 0x000000000000  NOTY GLOB  D    0 UNDEF       cmn_err

So there's the potential culprits. We know vpnmod is a STREAMs driver, and that it feels the need to tell us whenever it gets an unload request, so let's try to narrow down where that might be. If we look at the Device Driver Entry Points section of the 'Writing Device Drivers' manual, we can see that all loadable modules (including STREAMS drivers) have to implement the _init, _fini and _info entry points, and that the _fini entry point is called when a module is being unloaded, so that looks like the obvious place to start.

#  dis -F _fini vpnmod.sparc.64 | less
                ****   DISASSEMBLER  ****

disassembly for vpnmod.sparc.64

section .text
    _init+0x120:            9d e3 bf 30  save         %sp, -0xd0, %sp
    _init+0x124:            11 00 00 00  sethi        %hi(0x0), %o0
    _init+0x128:            90 12 20 00  or           %o0, vpn_open, %o0        ! vpn_open
    _init+0x12c:            91 2a 30 20  sllx         %o0, 32, %o0
    _init+0x130:            13 00 00 00  sethi        %hi(0x0), %o1
    _init+0x134:            90 02 00 09  add          %o0, %o1, %o0
    _init+0x138:            90 12 20 00  or           %o0, 0x0, %o0
    _init+0x13c:            40 00 00 00  call         _init+0x13c
    _init+0x140:            01 00 00 00  nop          
    _init+0x144:            d0 27 a7 eb  st           %o0, [%fp + 0x7eb]
    _init+0x148:            d0 07 a7 eb  ld           [%fp + 0x7eb], %o0
    _init+0x14c:            80 a2 20 00  cmp          %o0, 0x0
    _init+0x150:            12 48 00 13  bne,pt       %icc, _init+0x19c
    _init+0x154:            01 00 00 00  nop          
    _init+0x158:            11 00 00 00  sethi        %hi(0x0), %o0
    _init+0x15c:            d0 77 a7 df  stx          %o0, [%fp + 0x7df]
    _init+0x160:            d2 5f a7 df  ldx          [%fp + 0x7df], %o1
    _init+0x164:            92 12 60 00  or           %o1, 0x0, %o1
    _init+0x168:            d2 77 a7 df  stx          %o1, [%fp + 0x7df]
    _init+0x16c:            d0 5f a7 df  ldx          [%fp + 0x7df], %o0
    _init+0x170:            91 2a 30 20  sllx         %o0, 32, %o0
    _init+0x174:            d0 77 a7 df  stx          %o0, [%fp + 0x7df]
    _init+0x178:            11 00 00 00  sethi        %hi(0x0), %o0
    _init+0x17c:            d2 5f a7 df  ldx          [%fp + 0x7df], %o1
    _init+0x180:            92 02 40 08  add          %o1, %o0, %o1
    _init+0x184:            d2 77 a7 df  stx          %o1, [%fp + 0x7df]
    _init+0x188:            d0 5f a7 df  ldx          [%fp + 0x7df], %o0
    _init+0x18c:            90 12 20 00  or           %o0, 0x0, %o0
    _init+0x190:            d0 77 a7 df  stx          %o0, [%fp + 0x7df]
    _init+0x194:            10 68 00 11  ba,pt        %xcc, _init+0x1d8
    _init+0x198:            01 00 00 00  nop          
    _init+0x19c:            13 00 00 00  sethi        %hi(0x0), %o1
    _init+0x1a0:            d2 77 a7 df  stx          %o1, [%fp + 0x7df]

    _init+0x1a4:            d0 5f a7 df  ldx          [%fp + 0x7df], %o0
    _init+0x1a8:            90 12 20 00  or           %o0, 0x0, %o0
    _init+0x1ac:            d0 77 a7 df  stx          %o0, [%fp + 0x7df]
    _init+0x1b0:            d2 5f a7 df  ldx          [%fp + 0x7df], %o1
    _init+0x1b4:            93 2a 70 20  sllx         %o1, 32, %o1
    _init+0x1b8:            d2 77 a7 df  stx          %o1, [%fp + 0x7df]
    _init+0x1bc:            11 00 00 00  sethi        %hi(0x0), %o0
    _init+0x1c0:            d2 5f a7 df  ldx          [%fp + 0x7df], %o1
    _init+0x1c4:            92 02 40 08  add          %o1, %o0, %o1
    _init+0x1c8:            d2 77 a7 df  stx          %o1, [%fp + 0x7df]
    _init+0x1cc:            d0 5f a7 df  ldx          [%fp + 0x7df], %o0
    _init+0x1d0:            90 12 20 00  or           %o0, 0x0, %o0
    _init+0x1d4:            d0 77 a7 df  stx          %o0, [%fp + 0x7df]
    _init+0x1d8:            90 10 20 00  clr          %o0
    _init+0x1dc:            13 00 00 00  sethi        %hi(0x0), %o1
    _init+0x1e0:            92 12 60 00  or           %o1, vpn_open, %o1        ! vpn_open
    _init+0x1e4:            93 2a 70 20  sllx         %o1, 32, %o1
    _init+0x1e8:            15 00 00 00  sethi        %hi(0x0), %o2
    _init+0x1ec:            92 02 40 0a  add          %o1, %o2, %o1
    _init+0x1f0:            92 12 60 00  or           %o1, 0x0, %o1
    _init+0x1f4:            15 00 00 00  sethi        %hi(0x0), %o2
    _init+0x1f8:            94 12 a0 00  or           %o2, vpn_open, %o2        ! vpn_open
    _init+0x1fc:            95 2a b0 20  sllx         %o2, 32, %o2
    _init+0x200:            17 00 00 00  sethi        %hi(0x0), %o3
    _init+0x204:            94 02 80 0b  add          %o2, %o3, %o2
    _init+0x208:            94 12 a0 00  or           %o2, 0x0, %o2
    _init+0x20c:            d6 5f a7 df  ldx          [%fp + 0x7df], %o3
    _init+0x210:            19 00 00 00  sethi        %hi(0x0), %o4
    _init+0x214:            98 13 20 00  or           %o4, vpn_open, %o4        ! vpn_open
    _init+0x218:            99 2b 30 20  sllx         %o4, 32, %o4
    _init+0x21c:            1b 00 00 00  sethi        %hi(0x0), %o5
    _init+0x220:            98 03 00 0d  add          %o4, %o5, %o4
    _init+0x224:            98 13 20 00  or           %o4, 0x0, %o4
    _init+0x228:            40 00 00 00  call         _init+0x228
    _init+0x22c:            01 00 00 00  nop          
    _init+0x230:            d0 47 a7 eb  ldsw         [%fp + 0x7eb], %o0
    _init+0x234:            b0 10 00 08  mov          %o0, %i0
    _init+0x238:            81 cf e0 08  return       %i7 + 0x8
    _init+0x23c:            01 00 00 00  nop          

Hmm, wait a minute, there doesn't apppear to be any calls to cmn_err and friends in there, and if we look carefully at the call instructions we notice that the calls all call the location of the call instruction itself - what on earth is happening? Well, loadable modules are more-or-less standard ELF files, and when they are loaded into the kernel they undergo the same kind of link editing as userland ELF files get from What we actually need to do is to look at the function after relocation, and the easiest way to do that is to look on a running system using mdb:

# mdb -k
Loading modules: [ unix krtld genunix specfs ufs sd ip sctp usba s1394 nca
crypto random nfs audiosup ptm ipc ]
> vpnmod`_fini ::dis
vpnmod`_fini:                   save      %sp, -0xd0, %sp
vpnmod`_fini+4:                 sethi     %hi(0), %o0
vpnmod`_fini+8:                 or        %o0, 0, %o0
vpnmod`_fini+0xc:               sllx      %o0, 0x20, %o0
vpnmod`_fini+0x10:              sethi     %hi(0x70150000), %o1
vpnmod`_fini+0x14:              add       %o0, %o1, %o0
vpnmod`_fini+0x18:              or        %o0, 0x130, %o0
vpnmod`_fini+0x1c:              call      -0x7a3d10b8   <mod_remove>
vpnmod`_fini+0x20:              nop
vpnmod`_fini+0x24:              st        %o0, [%fp + 0x7eb]
vpnmod`_fini+0x28:              ld        [%fp + 0x7eb], %o0
vpnmod`_fini+0x2c:              cmp       %o0, 0
vpnmod`_fini+0x30:              bne,pt    %icc, +0x4c   <vpnmod`_fini+0x7c>
vpnmod`_fini+0x34:              nop
vpnmod`_fini+0x38:              sethi     %hi(0), %o0
vpnmod`_fini+0x3c:              stx       %o0, [%fp + 0x7df]
vpnmod`_fini+0x40:              ldx       [%fp + 0x7df], %o1
vpnmod`_fini+0x44:              or        %o1, 0, %o1
vpnmod`_fini+0x48:              stx       %o1, [%fp + 0x7df]
vpnmod`_fini+0x4c:              ldx       [%fp + 0x7df], %o0
vpnmod`_fini+0x50:              sllx      %o0, 0x20, %o0
vpnmod`_fini+0x54:              stx       %o0, [%fp + 0x7df]
vpnmod`_fini+0x58:              sethi     %hi(0x7b61c800), %o0
vpnmod`_fini+0x5c:              ldx       [%fp + 0x7df], %o1
vpnmod`_fini+0x60:              add       %o1, %o0, %o1
vpnmod`_fini+0x64:              stx       %o1, [%fp + 0x7df]
vpnmod`_fini+0x68:              ldx       [%fp + 0x7df], %o0
vpnmod`_fini+0x6c:              or        %o0, 0x60, %o0
vpnmod`_fini+0x70:              stx       %o0, [%fp + 0x7df]
vpnmod`_fini+0x74:              ba,pt     %xcc, +0x44   
vpnmod`_fini+0x78:              nop
vpnmod`_fini+0x7c:              sethi     %hi(0), %o1
vpnmod`_fini+0x80:              stx       %o1, [%fp + 0x7df]
vpnmod`_fini+0x84:              ldx       [%fp + 0x7df], %o0
vpnmod`_fini+0x88:              or        %o0, 0, %o0
vpnmod`_fini+0x8c:              stx       %o0, [%fp + 0x7df]
vpnmod`_fini+0x90:              ldx       [%fp + 0x7df], %o1
vpnmod`_fini+0x94:              sllx      %o1, 0x20, %o1
vpnmod`_fini+0x98:              stx       %o1, [%fp + 0x7df]
vpnmod`_fini+0x9c:              sethi     %hi(0x7b61c800), %o0
vpnmod`_fini+0xa0:              ldx       [%fp + 0x7df], %o1
vpnmod`_fini+0xa4:              add       %o1, %o0, %o1
vpnmod`_fini+0xa8:              stx       %o1, [%fp + 0x7df]
vpnmod`_fini+0xac:              ldx       [%fp + 0x7df], %o0
vpnmod`_fini+0xb0:              or        %o0, 0x98, %o0
vpnmod`_fini+0xb4:              stx       %o0, [%fp + 0x7df]
vpnmod`_fini+0xb8:              clr       %o0
vpnmod`_fini+0xbc:              sethi     %hi(0), %o1
vpnmod`_fini+0xc0:              or        %o1, 0, %o1
vpnmod`_fini+0xc4:              sllx      %o1, 0x20, %o1
vpnmod`_fini+0xc8:              sethi     %hi(0x7b61c800), %o2
vpnmod`_fini+0xcc:              add       %o1, %o2, %o1
vpnmod`_fini+0xd0:              or        %o1, 0xa0, %o1
vpnmod`_fini+0xd4:              sethi     %hi(0), %o2
vpnmod`_fini+0xd8:              or        %o2, 0, %o2
vpnmod`_fini+0xdc:              sllx      %o2, 0x20, %o2
vpnmod`_fini+0xe0:              sethi     %hi(0x7b61c800), %o3
vpnmod`_fini+0xe4:              add       %o2, %o3, %o2
vpnmod`_fini+0xe8:              or        %o2, 0x90, %o2
vpnmod`_fini+0xec:              ldx       [%fp + 0x7df], %o3
vpnmod`_fini+0xf0:              sethi     %hi(0), %o4
vpnmod`_fini+0xf4:              or        %o4, 0, %o4
vpnmod`_fini+0xf8:              sllx      %o4, 0x20, %o4
vpnmod`_fini+0xfc:              sethi     %hi(0x7b61d400), %o5
vpnmod`_fini+0x100:             add       %o4, %o5, %o4
vpnmod`_fini+0x104:             or        %o4, 0x3d0, %o4
vpnmod`_fini+0x108:             call      -0x7a4a2388   <cmn_err>
vpnmod`_fini+0x10c:             nop
vpnmod`_fini+0x110:             ldsw      [%fp + 0x7eb], %o0
vpnmod`_fini+0x114:             mov       %o0, %i0
vpnmod`_fini+0x118:             return    %i7 + 8
vpnmod`_fini+0x11c:             nop

Ahah! At vpnmod`_fini+0x108 there's a call to cmn_err. If we look a the cmn_err manpage, we see the prototype is void cmn_err(int level, char *format...);, so the format string will be passed in the %o2 register, this being sparc. Looking back through the disassembly, we can work out that %o2 will have the value 0x7b61c8a0 at the time of the call to cmn_err. Back to mdb:

> 0x7b61c8a0/S
0x7b61c8a0:     VPN Module %s Unload %s (%s)\n

Bingo. That matches the string we are seeing printed to /dev/console, so we have identified the offending call, all we now have to do is to get rid of it. The obvious thing is to replace the call with a nop instruction. We can calculate the offset of the offending instruction fairly easily: we know the offset fom the beginning of the _fini routine, it's 0x108, and we can use dump to tell us the start address of the routine:

# dump -t -n _fini vpnmod.sparc.64


              ***** SYMBOL TABLE INFORMATION *****

[Index]  Value           Size         Type	Bind	Other	Shndx	Name
[252]	 0x1ca4          115724       2		1	0	0x1	_fini

So that puts the offending call instruction at 0x1ca4 + 0x108 or 0x1dac from the start of the vpnmod code segment. Let's just double-check we are right with mdb (output shortened for clarity):

> ::modinfo
100         7b600000    1f650   1 vpnmod (VPN module)
> 7b600000+0x1dac ::dis
vpnmod`_fini+0x108:             call      -0x7a4a2388   <cmn_err>

Yep, that works. However, an ELF file such as vpnmod isn't a straight memory image, so we can't just seek that number of bytes into the file and write a nop in there, we need to make sure it's the correct offset from the start of the segment that holds the code - the .text segment. We can find that bit of information out as follows:

# dump -hvn .text vpnmod.sparc.64  


[No]	Type	Flags	Addr           Offset         Size            Name
	Link	Info	Adralgn        Entsize

[1]	PBIT    -AI	0              0x40           0x1c40c         .text
	0	0	0x8            0              

So that's telling us that the .text (code) segment of the ELF file is 0x40 bytes from the start of the file, which means that we can finally calculate the position within the ELF file of the instruction we want to nop out - <offset of .text section in file> + <offset of _fini routine from start of .text segment> + <offset of call instruction from start of _fini> = 0x40 + 0x1ca4 + 0x108 = 0x1dec. Yay! A we have to do is splat a nop over the 4 bytes starting at that position and we are done, right?

No, unfortunately not. Remember I said that the kernel link-edits the module as it loads it in? Well, if we just nop the offending instruction krtld (the kernel linker) will still attempt to relocate the call to cmn_err, specifically it assumes the first byte is already a call opcode (0x40) and it will write the offset to cmn_err into the 2nd, 3rd and 4th bytes of the call instruction - only it won't be a valid call instruction any more as we've just written a nop over the top of it. Damn.

What we need to do is to prevent the kernel performing the relocation for the call that we wish to nop out. How on earth do we do that? Well, let's poke around inside the ELF file some more. We can use elfdump to dump out the relocation information in the file, and we already know that the relocation we are looking for is for a call to cmn_err that is 0x1dac bytes from the start of the .text segment.

# elfdump -r vpnmod.sparc.64 | less           

Relocation Section:  .rela.text
        type                          offset     addend  section        with respect to
        R_SPARC_WDISP30               0x1c8c          0  .rela.text     cmn_err  
        R_SPARC_WDISP30               0x1dac          0  .rela.text     cmn_err  
        R_SPARC_WDISP30               0x1e18          0  .rela.text     cmn_err  

There it is. A quick read of the libgelf manpage reveals the following information:

           Retrieves the  Elf32_Rela  or  Elf64_Rela  information
           from  the  relocation  table  at  the given index. dst
           points to the location where the GElf_Rela  relocation
           entry will be stored.

So it's off to /usr/include to find the definition of Elf64_Rela:

typedef struct {
	Elf64_Addr	r_offset;
	Elf64_Xword	r_info;		/* sym, type: ELF64_R_... */
	Elf64_Sxword	r_addend;
} Elf64_Rela;

OK, let's see if we can persuade the linker to change what it does with the relocation that we want to nobble. Searching for the existing relocation type, R_SPARC_WDISP30, in the /usr/include header files reveals this:

#define R_SPARC_NONE		0		/* relocation type */
#define R_SPARC_8		1
#define R_SPARC_16		2
#define R_SPARC_32		3
#define R_SPARC_DISP8		4
#define R_SPARC_DISP16		5
#define R_SPARC_DISP32		6
#define R_SPARC_WDISP30		7

Hmm, that R_SPARC_NONE sure looks interesting. At this point we suspect that the mighty Linker and Libraries Guide may have some words of wisdom - although it documents the workings of ld and, much of the information on how ELF files work is also applicable to the kernel. Sure enough, Chapter 7 on Object File Format has a strong hint that R_SPARC_NONE relocations are ignored by the linker, so if we set the r_info field of the appropriate Elf64_Rela entry in the .rela.text section to R_SPARC_NONE we should be able to get the kernel linker to ignore the relocation for the call we wish to nop out. At this point, I went off and looked at the source of the krtld, the kernel linker to confirm that this was in fact what happened - an option that once Solaris is released as Open Source will be open to you as well :-)

Our story is almost told - the process of overwriting the appropriate relocation table section is much the same as that used for nop-ing out the function call - find the start of the .rela.text table in the ELF file, find the index in the .rela.text table of the entry we want to null out, write zeros over it, and we're done.

Those of you who have lasted this far are probably asking "What on earth has this got to do with perl?". Well, there are some slight differences between the way this has to be done on 32-bit sparc, 64-bit sparc and i386, and I needed fixed versions of the VPN module for all those platforms. The vpnmod module is also unnecessarily chatty when it's loaded up during boot, and I wanted to shut it up then as well. I therefore wrote a perl script to do all this automatically. Unfortunately we aren't permitted to post source code on our blogs so I can't share it with you, but I can let you see it in action:

# patchmod _fini+0x108 vpnmod.sparc.64 vpnmod.sparc.64.patched
.text segment base is 0x40, length is 0x1c40c
.rela.text segment base is 0x21808, length is 0x11880,
    each entry is 0x18 bytes long
function _fini base is 0x1ca4, length is 0x1c40c
call opcode is at offset 0x1dac in the .text segment
call opcode is at offset 0x1dec in the file
relocation for address 0x1dac is at index 363 in .rela.text,
    and is a call to cmn_err
relocation table entry is at offset 0x23a10 in the file
copying and patching file

And if we dig around with dis and dump we can see that the script has had the desired effect:

# dis -F _fini vpnmod.sparc.64.patched | less
    _init+0x218:            99 2b 30 20  sllx         %o4, 32, %o4
    _init+0x21c:            1b 00 00 00  sethi        %hi(0x0), %o5
    _init+0x220:            98 03 00 0d  add          %o4, %o5, %o4
    _init+0x224:            98 13 20 00  or           %o4, 0x0, %o4
    _init+0x228:            01 00 00 00  nop          
    _init+0x22c:            01 00 00 00  nop          
    _init+0x230:            d0 47 a7 eb  ldsw         [%fp + 0x7eb], %o0
    _init+0x234:            b0 10 00 08  mov          %o0, %i0
    _init+0x238:            81 cf e0 08  return       %i7 + 0x8
# dump -rvp -n .rela.text vpnmod.sparc.64.patched | less
0x1c8c		cmn_err			R_SPARC_WDISP30	  0
0		0			R_SPARC_NONE	  0
0x1e18		cmn_err			R_SPARC_WDISP30	  0

It's worth noting that I could have done this all in C - Solaris has libraries for directly manipulating ELF files, see the gelf(3ELF) and elf(3ELF) manpages, but hey, I was in a hurry ;-)

Tags : , , ,
Categories : Solaris, Perl, Work

Moors for the Future and CROW updates

Open AccessThe CROW (Countryside Rights Of Way) Act came into force in the Peak District on September 19th, the picture to the left is the new sign that you'll see on gates and stiles to show you where access land starts. There's a wealth of information available on the web - what your new rights are, where you can and can't go etc. There's even an on-line database showing any current access restrictions, complete with maps. I've also noticed that the Moors for the Future website has been completely revamped, and there's a wealth of new information on the site - well worth a visit if you are interested on the whys and wherefores of the Bleaklow restoration. Plus they have a link to this site, which shows they are a discerning bunch to boot :-)

Categories : Peak District

Following the fence

As part of the measures undertaken by the Moors for the Future project, English Nature have erected a fence around the most severely eroded part of the Bleaklow area. One of the jobs that Fiona, the full-time ranger has been asking for us to do it to survey the fence - where it actually goes as opposed to where it was originally planned, and where the stiles and gates are - the fence is designed to keep sheep out rather than people, so that the vegetation has time to regenerate. After much procrastination, I decided to actually make a start on this during yesterday's patrol. Although the fence has only been complete for less than a year, the picture below show that the dramatic effect that it has had already had - in the past this grass would have been grazed down to billiard-table level by the sheep.


The light brown material you can see on the edges of the peat haggs is the geojute matting that has been put down to stabilize the peat surface so it will re-vegetate. As well as measures such as the fence and geojute, there has also been an extensive program of seeding, liming and fertilizing - because of the fragile nature of the terrain this has all had to be done by helicopter. In the picture below, the verdant green grass has been sown as a nurse crop - the idea is to stabilise the peat surface long enough for the natural vegetation to establish itself, at which point the lime and fertilizer inputs will be discontinued and the nurse crop will die off - quite a clever idea. The longer reddish grass is the existing wavy hair grass (Deschampsia flexosa) which under the influence of the lime and fertiliser has grown strongly and seeded - and the natural seed will further improve the ground cover next year. In fact in some places the grass (both sown and existing) is doing so well we joke about it being more like the Serengeti than Bleaklow, and it seems from the picture below that the local wildlife appreciates the change as well.


Anyway, back to the fence survey. Dave and I got dropped off at Snake Summit and started to follow the fence line towards Crooked Clough. The first leg across the flat moor just east of Urchin Clough wasn't too bad, but once we crossed Doctor's Gate and started to traverse along the side of Crooked Clough it got considerably tougher. The survey technique is quite simple - I use a normal GPS, and use the track log to create a 'crumb trail' of where I've walked. As long as I stay within a couple of metres of the fence, the track log will record the path of the fence closely enough for our purposes. I also record a waypoint at every gate and stile, and then when I get back to the ranch I use OziExplorer to plot both the track log and the waypoints so I can overlay them on an Ordnance Survey map. For those of you that know the area, the segment of the fence that we surveyed starts at Snake Summit, crosses over Crooked Clough, skirts around underneath Shelf Stones and James Thorn before crossing Ferny Hole and plunging down Yellowslacks, up out of the other side and crossing Harrop Moss towards Torside Castle before crossing the Pennine Way in Torside Clough. Although we only walked about 9km, all the upping and downing plus the fairly rough terrain meant we'd both had enough by the time we reached the Pennine Way. We then walked off down the Pennine Way to Torside car park to wait for our lift back to the briefing centre. Bearing in mind the fence goes as far east as Grinah, I expect that it will take another 4-5 patrols to survey the whole thing and close the loop. While we were waiting at Torside we were talking to Diane who runs the cafe on the site - she's going to be open from 11:00am to 4:00pm from now on, so if you're passing that way, drop in for a cuppa!

Perl golf

My friend Stephen has posted a little challenge over on his blog. Basically it's to put a wrapper arond cal(1) so that if it is given a single argument between 1 and 12 or 'now' it prints a 3-month calendar centered around that month in the year, rather than the default behaviour which is to print a calendar for the year 1 through 12 - duh!

I of course took it as a perl golf challenge to produce the smallest (and therefore most unreadable) version possible. I know a few of my friends in perl-land read this blog, so perhaps you can come up with something even smaller than my current 404-byte version? To be fair, obvious hacks such as removing the die or shortening the /usr/bin/cal path are considered to be cheating ;-)

Here's my current effort, line breaks added to stop it sending your browser mental.

if($_ eq'now'){$a[1]=[$m,$y]}elsif($_=~/^\d+$/&&$_>=1&&$_<=12){$a[1]=[$_,$y]}
@c=map[map{chomp;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",
map shift@$_||'',@c for 1..7

Can you do better?


Thanks to Jason Santos for spotting a bug, and being devious enough to get the count down even further - here's the latest version, see if you can spot the differences:

@c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",
map shift@$_||'',@c for 1..8
Tags : , ,
Categories : Tech, Perl, Work