How to get the SD Back

So – I’ve been messing around with Ubuntu on a NanoPi Duo setup with motherboard which has build in SSD – all is well. In this and similar systems we have a Windows-readable boot partition and a Linux root partition with everything else except boot.

I copied the root partition (partition 1) over to the internal SSD – could just as easily be a USB stick – which left me with a 32GB SD doing nothing but booting the board… Like Raspberry PIs before version 3, I’m stuck with this for now. Seems such a WASTE.

I’ve done a fair bit of searching on Google and came to this… I broadly followed this to no avail. Here’s what I did – it LOOKED ok but simply will not boot..

So – it all seemed pretty easy in a 2-partition system (one for boot, one for filesystem) – make a primary partition on a smaller SD, make it bootable, copy everything from the boot folder – and Bob’s your uncle…. except no matter what, it would not boot!!!

Here’s what I did:

Prepared the sd - let's assume SDB for now

fdisk /dev/sdb

Assume no partitions - verified by p – and then make a new partition

n - new
p - primary

select default start and pick say +72261K  for a size

t c   - changes type to W95 FAT32 (LBA) -  I tried missing this also as my disk says P1 is of type Linux – that didn’t work either

a 1   - set partition 1 as boot

w  - write

Quit fdisk at this point and reboot to be safe – we’re assuming the SD shows up as SDB

mkfs.vfat  -F 16 -n "boot" /dev/sdb1

The above formats the partition as FAT

mkdir /mnt/sd1

mount /dev/sdb1 /mnt/sd1

cp -a /boot/. /mnt/sd1

umount /mnt/sd1

So basically I created a primary, bootable partition on the new SD, make it hopefully the right format – mounted it and copied the BOOT folder and subfolder across.  Remove the current boot SD – pop in the new on and…. nothing.

WELL it turns out this is all wrong because I missed out the bits you need to actually do the booting!!!

Here’s the original disk (I’m not actually using partition 2 as it is copied to an SSD)

Device         Boot  Start      End  Sectors  Size Id Type
/dev/mmcblk0p1       49152   131071    81920   40M 83 Linux
/dev/mmcblk0p2      131072 61405183 61274112 29.2G 83 Linux

and here’s the copy – aside from the start sector being different (I chose the default)

Device     Boot  Start      End  Sectors  Size Id Type
/dev/sdb1  *      2048   145407   143360   70M 83 Linux
/dev/sdb2       147456 31116287 30968832 14.8G 83 Linux

Just to show how little I understand this – the copy looks fine – but it does not work – comments below are turning a light on – at the beginning is boot info to actually start the process up – and copying that first partition is not quite enough.

Up to now thanks to comments in here, I used DD to copy everything from the start of the disk including the first partition and although the second was much larger than the destination disk, I just let it die at that point, swapped the disks over and voila, erased the truncated second partition – but that’s REALLY slow as it tries to fill the entire SD.

I was just thinking that rpi-clone with an option to ignore the second partition does just exactly what is needed here – readers have enlightened me to the fact that there is more than just the two partitions – there’s boot code in the first sectors.. and I’ve not a clue how to copy that across.

Update:

Now I was getting somewhere, if only I could stop DD at the end of the first partition. When I checked the original SD, here’s the output from “fdisk p”

Disk /dev/mmcblk0: 14.9 GiB, 15931539456 bytes, 31116288 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6c7ebba6

Device         Boot Start    End Sectors Size Id Type
/dev/mmcblk0p1      49152 131071   81920  40M 83 Linux

So we’re looking at 512 byte sectors or blocks – and the last one used in partition 1 is 131072…

So I reasoned this might work on a virgin SD

dd if=/dev/mmcblk0 of=/dev/sdb bs=512 count=131072

dd if=/dev/mmcblk0 of=/dev/sdb bs=512 count=131072 status=progress

(note – the status option only works on recent versions of Ubuntu)

In other words start at the very beginning, copying from the original SD (if or input file) to the new one (of or output file) – copying 512 byte blocks at a time until the end of the first partition.

And sure enough it worked– I put the new SD in and bingo….. though the copy knew about the second partition which it had not copied – so I simply wiped the second partition with fdisk  (fdisk – then d – then 2 – then w)

It just so happened – that I found an utterly useless 256MB microSD lying around – as this lot comes to 67MB in my case – I gave it a go. Voila.

Probably not clean but it worked and was quick and I get my decent size SD back!!

Better suggestions most welcome because this is a bit surgical. As my Googling fills in the blanks – I’m guessing the start of the SD contains the master boot record – which explains why the copy thought it had 2 partitions when in fact it only had one. After that I’m a little grey – I’m assuming  the U-BOOT stuff which actually does the boot startup – and then of course partition 1.

It would be nice to get a better version of this into a script – while making partition 1 no bigger than actually needed.  So in my file system it seems like the boot folder actually has 7 megabytes in it!  If you want to get REALLY into this – I’m starting to read this article – thanks to TKAISER for this…

And finally - thanks to the fellow who developed rpi-clone = Bill Wilson - the numbers are now automated... I added a bit at the end and so this script will copy from the bottom to the end of the current first partition – then create a second one, empty, with file system to fill remaining space.

#!/bin/bash
src_disk=mmcblk0
dst_disk=sdb
part2_start=$(fdisk -l | grep "^\/dev\/${src_disk}p2" | tr -s " " | cut -d " " -f 2)
echo "Copying original to $part2_start"
dd if=/dev/$src_disk of=/dev/$dst_disk bs=512 count=$part2_start status=progress
printf "d\n2\nn\np\n2\n$part2_start\n\nw\n" | fdisk /dev/$dst_disk
echo "Creating file system on /dev/${dst_disk}2"
mkfs.ext4 /dev/${dst_disk}2
exit  0

Just tried making this file - called it makesd  -  then ran "bash makesd" - and put a working boot onto a 128MB microSD I found lying around.

Facebooktwittergoogle_pluspinterestlinkedin

16 thoughts on “How to get the SD Back

      1. Ok, I was already confused since on the OPi Plus 2E there is 16GB pretty fast eMMC and since you ran Armbian on it the only possible answer would've been: 'sudo nand-sata-install' since this tool saves you from all the hassles.

        Back on topic: The only SBC who *need* a FAT partition are Raspberries since their proprietary bootloader can't deal with anything else. That's why we are used to these useless FAT /boot partitions that are not needed anywhere else. On Raspberries the primary OS running on the VideoCore gets loaded from the blobs on the FAT partition and then hands over later to the ARM cores that run the guest OS then (Linux usually).

        On almost all other SBC boot process is different, for Allwinner SoCs it's explained here in detail: http://linux-sunxi.org/Bootable_SD_card

        Depending on the OS image in question the way to tell the kernel where to look for the rootfs (and adjust /etc/fstab contents) might differ. Since it's 2017 I would not use device paths (move your rootfs to sda, attach later an USB thumb drive that then will be sda and watch your board not booting any more) and second Piper's suggestion to rely on PARTUUID instead.

        Since this whole 'get rootfs on something different than where the bootloader lives' procedere is just an insane waste of time Armbian provides a simple script that deals with almost all possible variations and also problems that might occur: https://github.com/armbian/build/blob/master/packages/bsp/common/usr/sbin/nand-sata-install

        Needs an Armbian installation of course so not of much use here with FriendlyELEC's OS image 🙁

        But as already said: doing this manually is a waste of time and as also already said: If I would play with a NanoPi Duo today I would start with an Armbian image for Orange Pi Zero since both boards are essentially the same from a software point of view (and Armbian users do it currently exactly that way without any issues).

    1. That didn't make a lot of sense to me however there was something I read just there suggesting that in some situations that actual starting block might be relevant. I'm not starting at the same place in the SD....

        1. Yes, FriendlyELEC uses u-boot 2017.01 or 2017.03 and u-boot + SPL is on the SD card.

          Just like Xunlong/OrangePi, Olimex and the Pine folks now also FriendlyELEC jumped on the 'Bootable SPI NOR flash' bandwagon and fortunately on the lower PCB side NanoPi Duo has soldered 16 Mb SPI NOR flash. Details: http://linux-sunxi.org/Bootable_SPI_flash

          So on this board the only really useful combination would be

          - u-boot+spl on SPI NOR flash
          - rootfs on USB storage (the mSATA SSD in this case)
          - no SD card needed any more

          The interesting question would be now: Does FriendlyELEC ship with the flash already prepopulated or not. Since their wiki doesn't mention anything wrt the SPI flash I would assume not.

          So next step would be to add these capabilities to a script that eases the whole procedure (taking the OS image on SD card, putting the necessary bootloader bits on SPI flash, moving the rootfs on USB storage, adjusts everything so that SD card isn't necessary any more).

          Not so surprisingly we (at Armbian) are currently working on exactly that so in a few weeks/months our nand-sata-install tool will also allow to use onboard SPI NOR flash for the bootloader part (everything else works already 🙂 )

          1. Do let us know when that happens TKAISER and I'll take a look. Meanwhile can you answer a question.. whenever I go looking for Armbian - here for example

            https://www.armbian.com/orange-pi-zero/

            The first thing I see is "legacy" - to me legacy means old. So not wanting to try experimental stuff - just exactly which version of Orange Pi Zero Server software is the latest stable one?

            Incidentally, using DD then going in, destroying the partial second partition and recreating it for general use - works a treat - it's just...... clumsy. There has to be a script that takes everything from sector zero to the end of the first partition an copies that to a new one - surely?

            1. Sure, I'll drop you a note once it's ready. Maybe the more important news for your readers is that while this SPI NOR flash we see on more and more boards these days and being empty both the original and final goal is to get the various hardware vendors shipping their boards with SPI NOR flash already containing an universal bootloader.

              This way every of these cheap boards gets the capabilities to boot from any USB attached storage, network (PXE), whatever. Comparable to what RPi 3 now allows just 'better' (the storage available on RPi 3 for USB/network boot is simply too small to put anything 'advanced' inside).

              Wrt Armbian and versions. 'Legacy' really means old and in case of all the H2+/H3 boards this means a 3.4.113 kernel. Though providing a stable mainline kernel branch (called 'Next') will happen soon. Main difference: Multimedia stuff will still only be available with legacy kernel since the necessary bits are still missing with mainline kernel. So currently the only stable/recommended Armbian releases for H2+/H3 boards base on the smelly 'legacy' kernel but 'next' is just around the corner and available in 1-2 months.

      1. With a working U-Boot and kernel on sd you can edit boot parameters for the kernel - point to the new partition. Try root=PARTUUID=uuid
        Try connecting via serial to the board with a working sd, stop U-Boot before it boots Linux.. you should be able to edit U-Boot parameters from within uboot's environment.

        1. Again - too much knowledge assumed. I have never noticed reference to u-boot and would not know how to stop this before it "boots Linux". Surely there must be a way not unsimilar to that which I've used, to merely get everything BUT the root (file system) partition onto a new SD? If the SD were the same size as the original, something as trivial as Win32DiskImager would do it but of course the point is to reduce the size of the SD as the relatively massive root partition is not needed here as it is elsewhere (and the file boot.,scr in the boot partition knows about that.

          1. Let’s try with the big SD first.
            1. Make a new one, or use one you already have. (probably done already).
            2. Copy root to ssd
            3. Edit boot.scr:
            a. Find root=/dev/ and change it to /dev/sda1
            4. Reboot, check if the system uses ssd for root
            5. If id does copy the big sd (part actually) to the new, small sd : dd if=/dev/mmcblk0 of=/dev/sdb
            not a pretty way to do it, but it should work (you actually need the starting blocks with all the booting software and uboot and the first partition, the fact that the second one is garbage doesn’t matter that much).
            6. reboot

            1. Hi

              That sector number thing - made no difference..

              I already know that I can make root point to mmcblk0p2 (the second partition on the SD) or SDA1 - which is on the SSD drive... (you have to edit boot.cmd then run a compile command line to get boot.scr.

              So the big SD - is right now using the SSD and not it's own second partition - that all works a treat and I can flick back and forth editing that file.

              So - the big SSD is not using it's second partition - so my assumption was that If I took that first partition - put it on a new SD, all would be well...

              But nothing's happening.

              Reading what you're saying DOES make sense... other than DD has to copy 16GB from the 32GB original - just to get a little 100 meg partition in place 🙂

              So - I tried it - and, well, it looked promising but 15 minutes later it's still going... the board hadn't crashed but dd is still doing something...

              Anyway I pulled the plug, confident that DD would be WAY past the first sector - and sure enough - it was - the machine booted from the new SD no problem.r

              The question is - is there a dd variation that will stop at the end of the first partition - or better - what am I missing in my version of doing this - some kind of pre-boot code? And is that why partition 1 doesn't start at block 0? And if so how do I get the bits before that onto a new SD?

              And thanks - one tiny step forward.... (it takes AGES for DD to copy the whole 16GB) - I'm assuming of course I could delete the braindead second partition and recreate it empty.. but there has to be a better way.

              1. For the location of bootloader stuff (SPL + u-boot) and why the partitions start where please see the link I already provided above.

                And yes, you can let dd only copy certain stuff but since this happens on a block device all the calculations (skip/seek/count parameters) you'd have to do yourself. As already said: I consider this whole stuff a huge waste of time and that's why we (Armbian) invest our time in this nand-sata-install tool to ease the whole procedure for every user.

                BTW: nand-sata-install is of course the wrong name these days (it started all with those Allwinner devices few years ago that had 'raw NAND' instead of eMMC as it's common today and also real SATA instead of USB). But unfortunately the other Armbian devs don't care to rename this to something more telling 🙂

  1. Check out the updated version of this blog (refresh) - I would not go so far as to say I totally understand this - but I know more than I did this morning - and just copied the boot code onto a 256MB SD - quickly and repeatably. Once spare SD recovered.

Leave a Reply

Your email address will not be published. Required fields are marked *