xref: /OK3568_Linux_fs/yocto/poky/scripts/contrib/ddimage (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1#!/bin/sh
2#
3# SPDX-License-Identifier: GPL-2.0-only
4#
5
6# 1MB blocksize
7BLOCKSIZE=1048576
8
9usage() {
10	echo "Usage: $(basename $0) IMAGE DEVICE"
11}
12
13image_details() {
14	IMG=$1
15	echo "Image details"
16	echo "============="
17	echo "    image: $(basename $IMG)"
18	# stat format is different on Mac OS and Linux
19	if [ "$(uname)" = "Darwin" ]; then
20		echo "     size: $(stat -L -f '%z bytes' $IMG)"
21		echo " modified: $(stat -L -f '%Sm' $IMG)"
22	else
23		echo "     size: $(stat -L -c '%s bytes' $IMG)"
24		echo " modified: $(stat -L -c '%y' $IMG)"
25	fi
26	echo "     type: $(file -L -b $IMG)"
27	echo ""
28}
29
30device_details() {
31	BLOCK_SIZE=512
32
33	echo "Device details"
34	echo "=============="
35
36	# Collect disk info using diskutil on Mac OS
37	if [ "$(uname)" = "Darwin" ]; then
38		diskutil info $DEVICE | egrep "(Device Node|Media Name|Total Size)"
39		return
40	fi
41
42	# Default / Linux information collection
43	ACTUAL_DEVICE=`readlink -f $DEVICE`
44	DEV=`basename $ACTUAL_DEVICE`
45	if [ "$ACTUAL_DEVICE" != "$DEVICE" ] ; then
46		echo "  device: $DEVICE -> $ACTUAL_DEVICE"
47	else
48		echo "  device: $DEVICE"
49	fi
50	if [ -f "/sys/class/block/$DEV/device/vendor" ]; then
51		echo "  vendor: $(cat /sys/class/block/$DEV/device/vendor)"
52	else
53		echo "  vendor: UNKNOWN"
54	fi
55	if [ -f "/sys/class/block/$DEV/device/model" ]; then
56		echo "   model: $(cat /sys/class/block/$DEV/device/model)"
57	else
58		echo "   model: UNKNOWN"
59	fi
60	if [ -f "/sys/class/block/$DEV/size" ]; then
61		echo "    size: $(($(cat /sys/class/block/$DEV/size) * $BLOCK_SIZE)) bytes"
62	else
63		echo "    size: UNKNOWN"
64	fi
65	echo ""
66}
67
68check_mount_device() {
69	if cat /proc/self/mounts | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1$" ; then
70		return 0
71	fi
72	return 1
73}
74
75is_mounted() {
76	if [ "$(uname)" = "Darwin" ]; then
77		if df | awk '{ print $1 }' | grep /dev/ | grep -q -E "^$1(s[0-9]+)?$" ; then
78			return 0
79		fi
80	else
81		if check_mount_device $1 ; then
82			return 0
83		fi
84		DEV=`basename $1`
85		if [ -d /sys/class/block/$DEV/ ] ; then
86			PARENT_BLKDEV=`basename $(readlink -f "/sys/class/block/$DEV/..")`
87			if [ "$PARENT_BLKDEV" != "block" ] ; then
88				if check_mount_device $PARENT_BLKDEV ; then
89					return 0
90				fi
91			fi
92			for CHILD_BLKDEV in `find /sys/class/block/$DEV/ -mindepth  1 -maxdepth 1 -name "$DEV*" -type d`
93			do
94				if check_mount_device /dev/`basename $CHILD_BLKDEV` ; then
95					return 0
96				fi
97			done
98		fi
99	fi
100	return 1
101}
102
103is_inuse() {
104	HOLDERS_DIR="/sys/class/block/`basename $1`/holders"
105	if [ -d $HOLDERS_DIR ] && [ `ls -A $HOLDERS_DIR` ] ; then
106		return 0
107	fi
108	return 1
109}
110
111if [ $# -ne 2 ]; then
112	usage
113	exit 1
114fi
115
116IMAGE=$1
117DEVICE=$2
118
119if [ ! -e "$IMAGE" ]; then
120	echo "ERROR: Image $IMAGE does not exist"
121	usage
122	exit 1
123fi
124
125if [ ! -e "$DEVICE" ]; then
126	echo "ERROR: Device $DEVICE does not exist"
127	usage
128	exit 1
129fi
130
131if [ "$(uname)" = "Darwin" ]; then
132	# readlink doesn't support -f on MacOS, just assume it isn't a symlink
133	ACTUAL_DEVICE=$DEVICE
134else
135	ACTUAL_DEVICE=`readlink -f $DEVICE`
136fi
137if is_mounted $ACTUAL_DEVICE ; then
138	echo "ERROR: Device $DEVICE is currently mounted - check if this is the right device, and unmount it first if so"
139	device_details
140	exit 1
141fi
142if is_inuse $ACTUAL_DEVICE ; then
143	echo "ERROR: Device $DEVICE is currently in use (possibly part of LVM) - check if this is the right device!"
144	device_details
145	exit 1
146fi
147
148if [ ! -w "$DEVICE" ]; then
149	echo "ERROR: Device $DEVICE is not writable - possibly use sudo?"
150	usage
151	exit 1
152fi
153
154image_details $IMAGE
155device_details
156
157printf "Write $IMAGE to $DEVICE [y/N]? "
158read RESPONSE
159if [ "$RESPONSE" != "y" ]; then
160	echo "Write aborted"
161	exit 0
162fi
163
164echo "Writing image..."
165if which pv >/dev/null 2>&1; then
166	pv "$IMAGE" | dd of="$DEVICE" bs="$BLOCKSIZE"
167else
168	dd if="$IMAGE" of="$DEVICE" bs="$BLOCKSIZE"
169fi
170sync
171