Skipping incompatible /lib/libpthread.so.0 when searching for /lib/libpthread.so.0

This normally happens when compiling for an arch, say ARM, and try to execute the binary in an x86_64 arch.
But in this case, it was not this problem, I was sure that I was compiling and executing for the right places for the right archs.

The error was the following:

/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.3/../../../../arm-linux-gnueabihf/bin/ld: skipping incompatible /lib/libpthread.so.0 when searching for /lib/libpthread.so.0
/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find /lib/libpthread.so.0

Then I discovered that the same issue appears with libc.so.6.
For some reason this happened after a Fedora upgrade, something got missing during the upgrade.

In order to fix it, change to the directory where your sysroot resides, in my case is /opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/sysroot

Edit the file usr/lib/libpthread.so.
Change the GROUP line that is where the linker searches for libpthread:

/*GROUP ( /lib/libpthread.so.0 /usr/lib/libpthread_nonshared.a )*/
GROUP ( libpthread.so.0 libpthread_nonshared.a )

Edit also the file usr/lib/libc.so:

/*GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux-armhf.so.3 ) )*/
GROUP ( libc.so.6 libc_nonshared.a  AS_NEEDED ( ld-linux-armhf.so.3 ) )

After this, I was able again to execute the binaries as before.

Adding a splashscreen in U-Boot in an Atmel based custom board

Normally, when you start an embedded Linux project you have an evaluation kit that comes with an LCD with a splashscreen in U-Boot. Then, when you have your custom board based on that evaluation board and if you’re lucky enough to use an LCD with the same characteristics, changing the splashscreen is an easy task. But if the LCD is quite different, you have to make some changes that are not difficult, but can take some time if you don’t know where to search.

Recently, I had to do just that with an Atmel SAMA5D3 board that was derived from the SAMA5D3 evaluation kit, but instead of mounting the default 800×400 LCD it mounts a 480×272 LCD with different characteristics such as clock frequency, horizontal/vertical syncs, and so on.

The default U-Boot configuration from Atmel (U-Boot 2015.01) does not support a splashscreen, only a raw image (logo) embedded in the code, so the first step is remove the support for the logo, enable the Atmel HLCD driver, enable the splashscreen and enable the bmp command that is needed to display the .bmp image.

These changes take place in the board header file that contains its configuration, in my case, it was the include/configs/sama5d3xek.h file.
This is a code snippet with the changes:

/* LCD */
#define CONFIG_LCD

/* Do not use LCD_COLOR32 or you'll get a BUG() and a bricked board */
#define LCD_BPP                     LCD_COLOR16

/* My board is an 24bit RGB */
#define LCD_OUTPUT_BPP              24

/* Comment these lines that enable the raw image logo */
/*#define CONFIG_LCD_LOGO*/
/*#define CONFIG_LCD_INFO*/
/*#define CONFIG_LCD_INFO_BELOW_LOGO*/
/*#define CONFIG_SYS_WHITE_ON_BLACK*/

/* Enable Atmel HLCD driver */
#define CONFIG_ATMEL_HLCD

/* For an Atmel based board is quite safe to use it, even though the LCD is a 24bit RGB */
#define CONFIG_ATMEL_LCD_RGB565
#define CONFIG_SYS_CONSOLE_IS_IN_ENV

/* Enable splashscreen */
#define CONFIG_SPLASH_SCREEN

/* Enable the bmp command */
#define CONFIG_CMD_BMP

/* Enable support for 16bit BMP */
#define CONFIG_BMP_16BPP

Some of these parameters could change for your LCD, such as LCD_OUTPUT_BPP. Adjust them according to the LCD datasheet.

Now you’ll probably have to change a couple of things: how the LCD is initialized by your board and how it is physically connected. In my case this is in board/atmel/sama5d3xek/sama5d3xek.c.

Set the parameters used to initialize the LCD. You may need to check its datasheet.

vidinfo_t panel_info = {
    .vl_col = 480,
    .vl_row = 272,
    .vl_clk = 9000000,
    .vl_bpix = LCD_BPP,
    .vl_bpox = LCD_OUTPUT_BPP,
    .vl_tft = 1,
    .vl_hsync_len = 45,
    .vl_left_margin = 10,
    .vl_right_margin = 10,
    .vl_vsync_len = 8,
    .vl_upper_margin = 10,
    .vl_lower_margin = 10,
    .mmio = ATMEL_BASE_LCDC,
};

Now check how the LCD is connected to the board. Mine has the higher 8 bit connected to peripheral A, while the evaluation kit’s higher 8 bit are connected to the peripheral C. You may need your board schematics to check to which peripheral is connected and change it accordingly:

at91_set_a_periph(AT91_PIO_PORTA, 16, 0);   /* LCDD16 */
at91_set_a_periph(AT91_PIO_PORTA, 17, 0);   /* LCDD17 */
at91_set_a_periph(AT91_PIO_PORTA, 18, 0);   /* LCDD18 */
at91_set_a_periph(AT91_PIO_PORTA, 19, 0);   /* LCDD19 */
at91_set_a_periph(AT91_PIO_PORTA, 20, 0);   /* LCDD20 */
at91_set_a_periph(AT91_PIO_PORTA, 21, 0);   /* LCDD21 */
at91_set_a_periph(AT91_PIO_PORTA, 22, 0);   /* LCDD22 */
at91_set_a_periph(AT91_PIO_PORTA, 23, 0);   /* LCDD23 */

At this point you should be able to have a nice boot splashscreen that you can change from userspace if you write to the right address.
A new post will describe how to do this.

References:
Official splashscreen U-Boot page.

Migrating from Trac to Redmine

In the past few days, I needed to migrate from a 6 years old server with CentOS 5 (it’s end of life is this month) to a shiny new one with Ubuntu 16.04. One of the services that was running in the old server was Trac 0.11 and I had several issues to move it to version 1.2. I like Trac and I’ve used it without any issues until now. After a while I decided to try Redmine 3.3.2, but I was not sure about the migration process.

After installing a large amount of requirements (a lot of Ruby packages), I followed this migration procedure that seemed straight-forward and should work with Trac 0.11, but it failed almost immediately for a very simple issue: The timestamps in all the database tables in Trac were in microseconds, whilst the script was expecting them in seconds.

I wrote this simple Perl script that changes the timestamps in all the Trac database tables:

#!/usr/bin/perl

use strict;
use DBI;
use POSIX;

my $dbh = DBI->connect(
    "dbi:SQLite:dbname=trac.db",
    "",
    "",
    { RaiseError => 1 },
) or die $DBI::errstr;

# attachment
print "Processing 'attachment' table ";
my $sth = $dbh->prepare("SELECT COUNT(*) FROM attachment");
$sth->execute() or die $DBI::errstr;
my $rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT type, id, filename, time FROM attachment");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($type, $id, $filename, $time) = $sth->fetchrow();

    $time = ceil($time / 1000000);
    my $sth2 = $dbh->prepare("UPDATE attachment SET time=$time WHERE type='$type' AND id='$id' AND filename='$filename'");
    $sth2->execute();
    $sth2->finish();

    print ".";
    $rows--;
}

$sth->finish();
print "\nDone\n\n";

# revision
print "Processing 'revision' table ";
$sth = $dbh->prepare("SELECT COUNT(*) FROM revision");
$sth->execute() or die $DBI::errstr;
$rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT repos, rev, time FROM revision");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($repos, $rev, $time) = $sth->fetchrow();

    $time = ceil($time / 1000000);
    my $sth2 = $dbh->prepare("UPDATE revision SET time=$time WHERE repos='$repos' AND rev='$rev'");
    $sth2->execute();
    $sth2->finish();

    print ".";
    $rows--;
}

$sth->finish();
print "\nDone\n\n";


# ticket
printf "Processing 'ticket' table";
$sth = $dbh->prepare("SELECT COUNT(*) FROM ticket");
$sth->execute() or die $DBI::errstr;
$rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT id, time, changetime FROM ticket");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($id, $time, $changetime) = $sth->fetchrow();

    $time = ceil($time / 1000000);
    $changetime = ceil($changetime / 1000000);
    my $sth2 = $dbh->prepare("UPDATE ticket SET time=$time, changetime=$changetime WHERE id='$id'");
    $sth2->execute();
    $sth2->finish();

    printf ".";
    $rows--;
}

$sth->finish();
printf "\nDone\n\n";

# ticket_change
print "Processing 'ticket_change' table ";
$sth = $dbh->prepare("SELECT COUNT(*) FROM ticket_change");
$sth->execute() or die $DBI::errstr;
$rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT ticket, time, author, field, oldvalue, newvalue FROM ticket_change");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($ticket, $time, $author, $field, $oldvalue, $newvalue) = $sth->fetchrow();

    #my $sth2 = $dbh->prepare("DELETE FROM ticket_change WHERE ticket='$ticket' AND time='$time' AND field='$field'");
    #$sth2->execute();

    my $prev_time = $time;
    $time = ceil($time / 1000000);
    #my $query = "INSERT INTO ticket_change (ticket, time, author, field, oldvalue, newvalue) VALUES ('$ticket', '$time', '$author', '$field', '".quotemeta($oldvalue)."', '".quotemeta($newvalue)."'";
    #printf("query: $query\n");
    #my $sth2 = $dbh->prepare($query);
    my $sth2 = $dbh->prepare("UPDATE ticket_change SET time='$time' WHERE ticket='$ticket' AND time='$prev_time' AND field='$field'");
    $sth2->execute();
    $sth2->finish();

    print ".";
    $rows--;
}

$sth->finish();
print "\nDone\n\n";

# version
print "Processing 'version' table ";
$sth = $dbh->prepare("SELECT COUNT(*) FROM version");
$sth->execute() or die $DBI::errstr;
$rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT name, time FROM version");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($name, $time) = $sth->fetchrow();

    $time = ceil($time / 1000000);
    my $sth2 = $dbh->prepare("UPDATE version SET time=$time WHERE name='$name'");
    $sth2->execute();
    $sth2->finish();

    print ".";
    $rows--;
}

$sth->finish();
print "\nDone\n\n";

# wiki
print "Processing 'wiki' table ";
$sth = $dbh->prepare("SELECT COUNT(*) FROM wiki");
$sth->execute() or die $DBI::errstr;
$rows = $sth->fetchrow();
$sth->finish();

$sth = $dbh->prepare("SELECT name, version, time FROM wiki");
$sth->execute() or die $DBI::errstr;

while ($rows) {
    my ($name, $version, $time) = $sth->fetchrow();

    $time = ceil($time / 1000000);
    my $sth2 = $dbh->prepare("UPDATE wiki SET time=$time WHERE name='$name' AND version='$version'");
    $sth2->execute();
    $sth2->finish();

    print ".";
    $rows--;
}

$sth->finish();
print "\nDone\n\n";

$dbh->disconnect();

Assuming that you have installed all the requirements (including the Perl ones with CPAN) and that the SQLite3 Trac database is called trac.db, execute the above script followed by the Redmine migration script:

# Make a copy of the trac database just in case...
cp trac.db trac.db.back

# Execute the Perl script that fixes the timestamps
perl trac2redmine.pl 

# Execute the Ruby migration script. Adjust the target environment, normally it is 'production'
rake redmine:migrate_from_trac RAILS_ENV="production"

The Ruby (rake) script asks for your Trac settings:

Trac directory []: /var/trac/myproject
Trac database adapter (sqlite, sqlite3, mysql, postgresql) [sqlite]:
Database encoding [UTF-8]:
Target project identifier []: myproject

and outputs all the items that were migrated without any errors.

I checked immediately in Redmine if everything was migrated correctly and I noticed a couple of issues:

  • The attachments in the wiki and tickets are not migrated
  • The wiki links are corrupted. The whole wiki was migrated (all the pages and their content is correct), but the links got corrupted.

The attachments were not a big issue since I had a few of them.
The wiki links was a bit annoying, I went to the Index by title, check the new name and edit the pages that link the correspondent page. My wiki is large, but it’s not heavily linked, so it didn’t take too much time to fix it.

Now that I’ve been using Redmine for a week I feel quite comfortable with it and I think that its integration with Git is better than Trac’s.