Another glitch I found out after upgrading to Debian Stretch was that my desktop's wireless NIC has started using the Chinese regulatory domain instead of guessing the correct country code where I'm living or simply using the value that was specified in the WiFi settings. For the record, it's a TP-LINK TL-WN881ND based on the Atheros AR9287 chipset.
I'm not sure if it's a bug in the central regulatory domain agent daemon (CRDA) that is shipped with Debian or something broken in this card's firmware. I'm leaning on the latter as the notebook is working as expected and the chipsets aren't the same. Anyway, because of international regulations about radio interference, it seems I can't nonchalantly set the correct country code of my network card, in fact according to the documentation1:
"The kernel ignores regulatory domains sent to it if it does not expect them."
Yup, it works as advertised.
Trying to launch, for example COUNTRY=US crda
from the command line, it fails and return -7
as exit code. By the way, is the same exit code that I've seen in the kernel logs2 where instead the crda is invoked from udev. In some ways the kernel isn't able to find which regulatory domain to set or doesn't agree with the value configured in /etc/default/crda
and it applies the value stored in the card's EEPROM.
Now, I think there's a documented procedure to override a regulatory domain that I've found described in the kernel.org's Wiki; it consists of creating and installing local crypto keys to sign a modified regulatory domains DB and it looked quite convoluted and boring. To be honest I didn't read the entire wall of text.
As I will explain later, after peeking in the card's firmware I've found out that it's present the China ISO/IEC 3166 country code on it even if the card was destined for the European market3, so I asked myself if it wouldn't be easier to simply alter two nimble bytes with the desired country code and called it a day. In other words, wouldn't be faster to have a chance to brick the wireless NIC trying to fix an allegedly broken firmware, maybe using a third party unmaintained tool of unknown quality?
Interestingly enough, even if not exactly a case of the Betteridge's law of headlines, the answer in this case is yes, with only a small hitch that I eventually solved.
After scouring the web I indeed found an abandoned utility on code.google.com called iwleeprom that allegedly had the ability to flash the card's firmware and after briefly examining the available documentation, a single terse man page, it really looked of unknown quality as it mentioned only Intel wireless card models.
With iwleeprom I was able to dump the information stored in the card's EEPROM, like capabilities, channels, MAC address and what I was looking for, the regulatory domain. In this particular case it reported the value 0x809c
. Ignoring the 0x8000
flag4, the value is 156
in decimal that corresponds to the China country code in the ISO/IEC 3166 list5.
Now it's only a matter of dumping the firmware, modifying it, calculating a new checksum, and writing it back on the card's EEPROM.
Regarding the small hitch I mentioned above, iwleeprom when dumping the firmware it calculates its checksum and reports the value stored on the card: the issue here is the two didn't matched. I suppose I can chalk this one as another thing that doesn't give confidence in the tool.
Undeterred I nonetheless tried to flash a modified firmware with the iwleeprom's calculated checksum and the obvious result was a soft brick. As I feared the wireless NIC refused to work with the applied changes.
Well, after looking at the kernel's ath9k sources, I managed to fix the checksum calculation; fortunately the change was trivial. The patch consists in commenting a single line in the iwleeprom's ath9k_eeprom_crc_calc
function:
static bool ath9k_eeprom_crc_calc(struct pcidev *dev, uint16_t *crcp)
{
uint16_t crc = 0, data;
int i;
if (!short_eeprom_size)
return false;
printf("Calculating EEPROM CRC");
for (i=0; i<short_eeprom_size; i+=2) {
if (2 == i) continue;
if (!dev->ops->eeprom_read16(dev, short_eeprom_base + i, &data)) {
printf(" !ERROR!\n");
return false;
}
crc ^= data;
if (!(i & 0xFFC0)) printf(".");
}
//crc ^= 0xFFFF; <-- The offending line
if (crcp)
*crcp = crc;
printf("\n");
return true;
}
The final exclusive OR with the 0xffff
constant isn't required for this chipset.
For the modification part the interesting bits, pun intended, start at location 0x0102
with two bytes for the checksum in little-endian format (in this case 0x9187
) followed by the two bytes of the country code at 0x0108
(in this case 0x809c
) again in little-endian format:
00000100 d7 02 87 91 04 e0 16 00 9c 80 1f 00 07 00 13 37
00000110 d0 0d 03 03 00 00 00 00 00 00 00 1b 09 00 05 01
00000120 fb fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
So after fixing the checksum calculation the plan is:
dumping the firmware with sudo ./iwleeprom -d 0000:03:00.0 -o /tmp/ar9287.bin
passing the correct PCI slot address with the -d
option
modifying the country code
launching ./iwleeprom -n -i /tmp/ar9287-mod.bin -s
to calculate a new checksum passing the -n
option to operate only on files
updating the checksum
flashing the modified firmware to the card's EEPROM with sudo ./iwleeprom -d 0000:03:00.0 -i /tmp/ar9287.bin
...
profit
I can assure the concerned reader that no wireless NIC was harmed performing the above procedure, in fact the mentioned card is now happily connected with my access point using the expected country regulatory domain.
As a final note, I'm not encouraging the reader to tinker with his WiFi hardware, this is merely a reference to be used by my future self. Messing with radio stuff is serious business, especially with interference, fines aren't a remote possibility.
quoting from the crda(8) man page ↩
in the kernel logs the exit code is 249, the decimal value of -7 in two's complement ↩
in my opinion they should have put a generic "world" regulatory domain instead of a specific country code ↩
according to the Atheros documentation it's the COUNTRY_ERD_FLAG
↩
the inquisitive reader can find the complete list on the Wikipedia page ↩
In my opinion, with good defaults options aren't needed. Options in software creates complexity, as all the code paths should be equally tested.
One always hope to encounter, if not good, at least reasonable defaults, especially in consumer hardware.
This post is about bad defaults.
Seagate has decided that their line of NAS hard disks1 needs to have a power saving feature, with two profiles enabled on the firmware as default. The first one has a default timeout of 10 seconds and a null impact on the mechanical hardware itself, as it only stops the current feeding the disc's heads. The conscious reader would have guessed that it also has negligible effects on power savings2.
The second enabled profile has a timeout of 240 seconds and it's more substantial than the first one as it parks the disc's heads on the drive ramp. For the reader unfamiliar with a drive internals, it's the heads' rest location, outside the disc platters.
So if the drive is idle for more than 4 minutes, the firmware unload the heads to the drive ramp. The number of times this operation is executed is recorded under the field labeled "load/unload cycle" in the disc's SMART data tally. Usually the discs mechanics are guaranteed for half a million load/unload cycles, after few months my disk reported nearly 40000 load/unload cycles.
Not good.
It has happened before, with other manufacturers it was even worst. If I recall correctly "Western Digital" had produced in the past disks with a similar behavior and didn't provided a modified firmware but instead they offered a DOS utility that periodically wrote a sector to avoid the disc to enter idle mode. If I'm not wrong, in that specific case the disc completely spin down: maximum power savings!
Fortunately Seagate offers an utility to modify the power saving's settings, it's a command line tool called sc-powerchoice or SeaChest_PowerChoice, available only as an IA32/AMD64 executable (no sources) inside a live Linux distribution that should be flashed on a USB memory stick. Unfortunately, again, it was only distributed as a Windows executable instead of a normal disk image3.
Groan.
Anyway, after extracting and locally mounting the disc image I was able to copy the "64-bit" version of the utility on my NAS and finally I was allowed to disable the second profile with:
$ sudo sc-powerchoice -d /dev/sg1 --changePower --powerMode idle_b --disableMode
where the drive path is found using the --scan
option and the command to show the current configuration is:
$ sudo sc-powerchoice -d /dev/sg1 -i --showEPCSettings
End of the rant.
There was a time when I boldly used the ever changing Debian's Sid flavor, but when the last stable version was released, Debian 8 code name "Jessie", I stuck with it. It seems has been ages but it's only a couple of years. Anyway when a few days ago I've learned that Debian 9 "Stretch" had a tentative release date set for June the 17, I decided it was time to give it a spin1.
"Stretch, the rubber purple octopus"
I'm not going to do a review, I've used it non extensively only for a couple of days and under the hood Debian looks the same. On the outside, the shipped Gnome version was released more than a year ago so it's somewhat old news, but to me it feels fresh and I definitely like the small changes to the appearance and to the environment, at least most of all.
For starters, one thing I'm less happy with, was the removal of the option to associate a menu to the physical power button. Now the choices when the button is pressed are: suspend, hibernate and doing nothing.
For the interested reader I'll report below the few lines that need to be patched in the gnome-settings-daemon
--- a/data/gsd-enums.h 2016-10-08 16:08:22.000000000 +0200
+++ b/data/gsd-enums.h 2017-05-31 07:56:53.069017123 +0200
@@ -113,6 +113,8 @@
typedef enum
{
GSD_POWER_BUTTON_ACTION_NOTHING,
+ GSD_POWER_BUTTON_ACTION_INTERACTIVE,
GSD_POWER_BUTTON_ACTION_SUSPEND,
GSD_POWER_BUTTON_ACTION_HIBERNATE
} GsdPowerButtonActionType;
--- a/plugins/media-keys/gsd-media-keys-manager.c 2017-05-31 08:26:10.000000000 +0200
+++ b/plugins/media-keys/gsd-media-keys-manager.c 2017-05-31 07:59:22.657383132 +0200
@@ -1990,6 +1990,12 @@
action_type = g_settings_get_enum (manager->priv->power_settings, "power-button-action");
switch (action_type) {
+ case GSD_POWER_BUTTON_ACTION_INTERACTIVE:
+ do_config_power_action (manager, GSD_POWER_ACTION_INTERACTIVE, in_lock_screen);
+ break;
case GSD_POWER_BUTTON_ACTION_SUSPEND:
do_config_power_action (manager, GSD_POWER_ACTION_SUSPEND, in_lock_screen);
break;
and the gnome-control-center
--- a/panels/power/cc-power-panel.c 2017-03-10 19:15:25.000000000 +0100
+++ b/panels/power/cc-power-panel.c 2017-05-31 08:41:15.447701349 +0200
@@ -2066,6 +2066,7 @@
} actions[] = {
{ N_("Suspend"), GSD_POWER_BUTTON_ACTION_SUSPEND },
{ N_("Hibernate"), GSD_POWER_BUTTON_ACTION_HIBERNATE },
+ { N_("Interactive"), GSD_POWER_BUTTON_ACTION_INTERACTIVE},
{ N_("Nothing"), GSD_POWER_BUTTON_ACTION_NOTHING }
};
guint i;
to bring back the functionality.
Unfortunately, I suspect the Debian Gnome Packaging Team comprehensibly would not accept changes like the above this late in the release process.
*Shrug* I can live with a couple of custom packages.
About other small problems I've found, the Gnome Online Accounts daemon, called goa-daemon, has a weird interaction with d-bus and the gnome-keyring. Basically, when a user log out, the goa-daemon is not killed2 and if the same user log in again, the still running goa-daemon process couldn't contact the new instance of the gnome-keyring. This breaks the on-line calendar, the default mail client and the third party remote storage desktop integration, in other words, the cloud stops to work.
Looks like it isn't fixed upstream yet, so my workaround is to check at log-in time if the daemon is running and replace it with a new instance if true. A simple way was creating a desktop file in my ~/.config/autostart
directory with the following content:
[Desktop Entry]
Name=Replace running goa-daemon
Exec=env sh -c 'pidof goa-daemon 1> /dev/null && /usr/lib/gnome-online-accounts/goa-daemon --replace'
NoDisplay=true
Terminal=false
Type=Application
My explanation above is very brief, the interested reader can check the bug #764029 filed on the Gnome bug tracking system for the gory details. The rabbit hole in this case is quite deep.
Another broken thing that I've found, although somewhat specific to my notebook model, was the iio-sensor-proxy happily spamming my log file with authorization errors3. I haven't exhaustively searched for a solution, but as it's related with all kinds of sensors interactions, like accelerometers, magnetometers, photodetectors and considering that I'm not interested in using the light sensor at the moment4, removing the iio-sensor-proxy package solved the issue.
That wasn't the only authorization error present in my logs, as I've found another one regarding lack of permissions accessing the display's ICC profile file. I don't have a solution for it yet but for my use case it's not critical and it happens only one time at the start of the session, so it can wait.
Edit: relaxing the permissions of the path /var/lib/gdm3/.local/share/icc/
fixed the error.
Even if not activated by default for the user session, Wayland/Weston is used by GDM, the Gnome log-in manager. I've tried a Wayland session once, and it seems to run without glitches on the notebook, but I'm too reliant on a couple of utilities that work only on X, xcape and libinput-gestures, so no Wayland for me yet.
With the transition to Wayland it was changed the way to enable the "tap to click" on the greeter's log-in screen, now there is a dconf Boolean key in the GDM user configuration to flip:
$ sudo su - Debian-gdm -s /bin/sh
$ export $(dbus-launch)
$ gsettings set org.gnome.desktop.peripherals.touchpad tap-to-click true
Speaking of the greeter, another thing I'm missing is the option to switch keyboard layout, and I was unable to find yet the configuration to regain the previous menu. I suspect I need to add the relevant dconf keys/values to the GDM user, if it's possible at all. Edit: in the notebook the greeter keyboard layout is set to Colemak so it's possible, if one day I'm really bored I'll try to figure out where is configured.
Anyway, having configured the keyboard with the Colemak layout and not having a simple way to switch to a different layout at log-in time, it will be a fun challenge/small deterrent for strangers.
As a side note, now on Debian the greeter starts from the first tty instead of the seventh. Color me surprised.
This should be filed under "yak shaving" as I was looking to force a complete blank screen during boot. I was mildly frustrated that, even if I explicitly passed the quiet
option and reduced the log level, there was still a message present a boot time about the check of the system partition(s).
At first I suspected the systemd-fsckd.service
, instead the culprit was the initramfs, or better the script inside the initramfs that execute the fsck command. With this knowledge, the quick fix was to appended a redirection to /dev/null
after the command invocation in the /usr/share/initramfs-tools/scripts/functions
file.
--- a/usr/share/initramfs-tools/scripts/functions 2017-06-02 19:01:42.459905047 +0200
+++ b/usr/share/initramfs-tools/scripts/functions 2017-06-02 19:00:58.093797696 +0200
@@ -386,7 +386,7 @@
log_end_msg
else
log_begin_msg "Checking $NAME file system"
- logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -T -t $TYPE $DEV
+ logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -T -t $TYPE $DEV > /dev/null
FSCKCODE=$?
log_end_msg
fi
I've also removed the super annoying blinking cursor, passing the vt.global_cursor_default=0
kernel boot directive.
my prediction was off by less than five weeks ↩
well, it's not the only process that is left running after a user log out, to be honest I was surprised by the number of lingering running processes ↩
if someone is interested, the error was "Error executing command as another user: Not authorized" from the gnome-settings-daemon ↩
IIRC it's used by the firmware as default to regulate the keyboard back-light, but could be used to adjust the screen brightness too ↩