1209513Simp#!/bin/sh
2209513Simp#-
3209552Simp# Copyright (c) 2010 iXsystems, Inc.  All rights reserved.
4209513Simp#
5209513Simp# Redistribution and use in source and binary forms, with or without
6209513Simp# modification, are permitted provided that the following conditions
7209513Simp# are met:
8209513Simp# 1. Redistributions of source code must retain the above copyright
9209513Simp#    notice, this list of conditions and the following disclaimer.
10209513Simp# 2. Redistributions in binary form must reproduce the above copyright
11209513Simp#    notice, this list of conditions and the following disclaimer in the
12209513Simp#    documentation and/or other materials provided with the distribution.
13209513Simp#
14209513Simp# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15209513Simp# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16209513Simp# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17209513Simp# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18209513Simp# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19209513Simp# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20209513Simp# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21209513Simp# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22209513Simp# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23209513Simp# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24209513Simp# SUCH DAMAGE.
25209513Simp#
26209513Simp# $FreeBSD$
27209513Simp
28209513Simp# Functions related to disk operations using bsdlabel
29209513Simp
30209513Simp# Check if we are are provided a geli password on the nextline of the config
31209513Simpcheck_for_enc_pass()
32209513Simp{
33209513Simp  CURLINE="${1}"
34209513Simp 
35209513Simp  get_next_cfg_line "${CFGF}" "${CURLINE}" 
36220059Sjpaetzel  echo ${VAL} | grep -q "^encpass=" 2>/dev/null
37220059Sjpaetzel  if [ $? -eq 0 ] ; then
38209513Simp    # Found a password, return it
39209513Simp    get_value_from_string "${VAL}"
40209513Simp    return
41209513Simp  fi
42209513Simp
43220059Sjpaetzel  export VAL=""
44209513Simp  return
45209513Simp};
46209513Simp
47209513Simp# On check on the disk-label line if we have any extra vars for this device
48209513Simpget_fs_line_xvars()
49209513Simp{
50209513Simp  ACTIVEDEV="${1}"
51209513Simp  LINE="${2}"
52209513Simp
53235445Sjpaetzel  echo $LINE | cut -d ' ' -f 4 | grep -q '(' 2>/dev/null
54235445Sjpaetzel  if [ $? -ne 0 ] ; then return ; fi
55235445Sjpaetzel
56235445Sjpaetzel  # See if we are looking for ZFS specific options
57235445Sjpaetzel  echo $LINE | grep -q '^ZFS' 2>/dev/null
58220059Sjpaetzel  if [ $? -eq 0 ] ; then
59235445Sjpaetzel    ZTYPE="NONE"
60235445Sjpaetzel    ZFSVARS="`echo $LINE | cut -d ' ' -f 4-20 |cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
61209513Simp
62235445Sjpaetzel    echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null
63220059Sjpaetzel    if [ $? -eq 0 ] ; then
64211488Simp       ZTYPE=`echo $ZFSVARS | cut -f1 -d:`
65211488Simp       ZFSVARS=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"`
66235445Sjpaetzel    fi
67209513Simp
68235445Sjpaetzel    # Return the ZFS options
69235445Sjpaetzel    if [ "${ZTYPE}" = "NONE" ] ; then
70235445Sjpaetzel      VAR="${ACTIVEDEV} ${ZFSVARS}"
71235445Sjpaetzel    else
72235445Sjpaetzel      VAR="${ZTYPE} ${ACTIVEDEV} ${ZFSVARS}"
73225657Sjpaetzel    fi
74235445Sjpaetzel    export VAR
75235445Sjpaetzel    return
76235445Sjpaetzel  fi # End of ZFS block
77225657Sjpaetzel
78235445Sjpaetzel  # See if we are looking for UFS specific newfs options
79235445Sjpaetzel  echo $LINE | grep -q '^UFS' 2>/dev/null
80235445Sjpaetzel  if [ $? -eq 0 ] ; then
81235445Sjpaetzel    FSVARS="`echo $LINE | cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
82235445Sjpaetzel    VAR="${FSVARS}"
83235445Sjpaetzel    export VAR
84235445Sjpaetzel    return
85235445Sjpaetzel  fi
86209513Simp
87209513Simp  # If we got here, set VAR to empty and export
88220059Sjpaetzel  export VAR=""
89209513Simp  return
90209513Simp};
91209513Simp
92209513Simp# Init each zfs mirror disk with a boot sector so we can failover
93211730Simpsetup_zfs_mirror_parts()
94211730Simp{
95211730Simp  _nZFS=""
96209513Simp
97235445Sjpaetzel  ZTYPE="`echo ${1} | awk '{print $1}'`"
98235445Sjpaetzel
99211730Simp  # Using mirroring, setup boot partitions on each disk
100235445Sjpaetzel  _mirrline="`echo ${1} | sed 's|mirror ||g' | sed 's|raidz1 ||g' | sed 's|raidz2 ||g' | sed 's|raidz3 ||g' | sed 's|raidz ||g'`"
101211730Simp  for _zvars in $_mirrline
102211730Simp  do
103211730Simp    echo "Looping through _zvars: $_zvars" >>${LOGOUT}
104220059Sjpaetzel    echo "$_zvars" | grep -q "${2}" 2>/dev/null
105220059Sjpaetzel    if [ $? -eq 0 ] ; then continue ; fi
106211730Simp    if [ -z "$_zvars" ] ; then continue ; fi
107211730Simp
108211730Simp    is_disk "$_zvars" >/dev/null 2>/dev/null
109220059Sjpaetzel    if [ $? -eq 0 ] ; then
110235445Sjpaetzel      echo "Setting up ZFS disk $_zvars" >>${LOGOUT}
111211730Simp      init_gpt_full_disk "$_zvars" >/dev/null 2>/dev/null
112235445Sjpaetzel      rc_halt "gpart add -a 4k -t freebsd-zfs ${_zvars}" >/dev/null 2>/dev/null
113235445Sjpaetzel      rc_halt "gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${_zvars}" >/dev/null 2>/dev/null
114211730Simp      _nZFS="$_nZFS ${_zvars}p2"	
115211730Simp    else
116211730Simp      _nZFS="$_nZFS ${_zvars}"	
117211730Simp    fi	
118211730Simp  done
119235445Sjpaetzel  echo "$ZTYPE $2 `echo $_nZFS | tr -s ' '`"
120209513Simp} ;
121209513Simp
122209513Simp# Function which creates a unique label name for the specified mount
123209513Simpgen_glabel_name()
124209513Simp{
125209513Simp  MOUNT="$1"
126209513Simp  TYPE="$2"
127209513Simp  NUM="0"
128209513Simp  MAXNUM="20"
129209513Simp
130233224Sjpaetzel  if [ "$TYPE" = "ZFS" ] ; then
131233224Sjpaetzel    NAME="zpool"
132233224Sjpaetzel  elif [ "$MOUNT" = "/" ] ; then
133209513Simp    NAME="rootfs"
134209513Simp  else
135209513Simp    # If doing a swap partition, also rename it
136209513Simp    if [ "${TYPE}" = "SWAP" ]
137209513Simp    then
138209513Simp      NAME="swap"
139209513Simp    else
140209513Simp      NAME="`echo $MOUNT | sed 's|/||g' | sed 's| ||g'`"
141209513Simp    fi
142209513Simp  fi
143209513Simp
144209513Simp  # Loop through and break when we find our first available label
145209513Simp  while
146209513Simp  Z=1
147209513Simp  do
148220059Sjpaetzel    glabel status | grep -q "${NAME}${NUM}" 2>/dev/null
149220059Sjpaetzel    if [ $? -ne 0 ]
150209513Simp    then
151209513Simp      break
152209513Simp    else
153220059Sjpaetzel        NUM=$((NUM+1))
154209513Simp    fi
155209513Simp
156209513Simp    if [ $NUM -gt $MAXNUM ]
157209513Simp    then
158209513Simp      exit_err "Cannot allocate additional glabel name for $NAME"
159209513Simp      break
160209513Simp    fi
161209513Simp  done 
162209513Simp   
163209513Simp
164220059Sjpaetzel  export VAL="${NAME}${NUM}" 
165209513Simp};
166209513Simp
167240315Sjpaetzel# Function to determine the size we can safely use when 0 is specified
168240315Sjpaetzelget_autosize()
169240315Sjpaetzel{
170240315Sjpaetzel  # Disk tag to look for
171240315Sjpaetzel  dTag="$1"
172240315Sjpaetzel
173240315Sjpaetzel  # Total MB Avail
174240315Sjpaetzel  get_disk_mediasize_mb "$2"
175240315Sjpaetzel  local _aSize=$VAL
176240315Sjpaetzel
177240315Sjpaetzel  while read line
178240315Sjpaetzel  do
179240315Sjpaetzel    # Check for data on this slice
180240315Sjpaetzel    echo $line | grep -q "^${_dTag}-part=" 2>/dev/null
181240315Sjpaetzel    if [ $? -ne 0 ] ; then continue ; fi
182240315Sjpaetzel
183240315Sjpaetzel    get_value_from_string "${line}"
184240315Sjpaetzel    STRING="$VAL"
185240315Sjpaetzel
186240315Sjpaetzel    # Get the size of this partition
187240315Sjpaetzel    SIZE=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 2` 
188240315Sjpaetzel    if [ $SIZE -eq 0 ] ; then continue ; fi
189240315Sjpaetzel    _aSize=`expr $_aSize - $SIZE`
190240315Sjpaetzel  done <${CFGF}
191240315Sjpaetzel
192240315Sjpaetzel  # Pad the size a bit
193240315Sjpaetzel  _aSize=`expr $_aSize - 2`
194240315Sjpaetzel
195240315Sjpaetzel  VAL="$_aSize"
196240315Sjpaetzel  export VAL
197240315Sjpaetzel};
198240315Sjpaetzel
199217229Sjpaetzel# Function to setup partitions using gpart
200217229Sjpaetzelsetup_gpart_partitions()
201209513Simp{
202217229Sjpaetzel  local _dTag="$1"
203217229Sjpaetzel  local _pDisk="$2"
204217229Sjpaetzel  local _wSlice="$3"
205217229Sjpaetzel  local _sNum="$4"
206217229Sjpaetzel  local _pType="$5"
207209513Simp  FOUNDPARTS="1"
208240315Sjpaetzel  USEDAUTOSIZE=0
209209513Simp
210217229Sjpaetzel  # Lets read in the config file now and setup our partitions
211217229Sjpaetzel  if [ "${_pType}" = "gpt" ] ; then
212217229Sjpaetzel    CURPART="2"
213235447Sjpaetzel  elif [ "${_pType}" = "apm" ] ; then
214235447Sjpaetzel    CURPART="3"
215217229Sjpaetzel  else
216217229Sjpaetzel    PARTLETTER="a"
217217229Sjpaetzel    CURPART="1"
218232415Sjpaetzel    if [ "${_pType}" = "mbr" ] ; then
219232415Sjpaetzel      rc_halt "gpart create -s BSD ${_wSlice}"
220232415Sjpaetzel    fi
221217229Sjpaetzel  fi
222209513Simp
223209513Simp  while read line
224209513Simp  do
225209513Simp    # Check for data on this slice
226220059Sjpaetzel    echo $line | grep -q "^${_dTag}-part=" 2>/dev/null
227220059Sjpaetzel    if [ $? -eq 0 ]
228209513Simp    then
229209513Simp      FOUNDPARTS="0"
230209513Simp      # Found a slice- entry, lets get the slice info
231209513Simp      get_value_from_string "${line}"
232209513Simp      STRING="$VAL"
233209513Simp
234209513Simp      # We need to split up the string now, and pick out the variables
235209513Simp      FS=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 1` 
236209513Simp      SIZE=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 2` 
237209513Simp      MNT=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 3` 
238209513Simp
239209513Simp      # Check if we have a .eli extension on this FS
240220059Sjpaetzel      echo ${FS} | grep -q ".eli" 2>/dev/null
241220059Sjpaetzel      if [ $? -eq 0 ]
242209513Simp      then
243209513Simp        FS="`echo ${FS} | cut -d '.' -f 1`"
244209513Simp        ENC="ON"
245209513Simp        check_for_enc_pass "${line}"
246209513Simp        if [ "${VAL}" != "" ] ; then
247209513Simp          # We have a user supplied password, save it for later
248209513Simp          ENCPASS="${VAL}" 
249209513Simp        fi
250209513Simp      else
251209513Simp        ENC="OFF"
252209513Simp      fi
253209513Simp
254209513Simp      # Check if the user tried to setup / as an encrypted partition
255209513Simp      check_for_mount "${MNT}" "/"
256220059Sjpaetzel      if [ $? -eq 0 -a "${ENC}" = "ON" ]
257209513Simp      then
258220059Sjpaetzel        export USINGENCROOT="0"
259209513Simp      fi
260209513Simp          
261209513Simp      # Now check that these values are sane
262209513Simp      case $FS in
263213647Simp        UFS|UFS+S|UFS+J|UFS+SUJ|ZFS|SWAP) ;;
264209513Simp       *) exit_err "ERROR: Invalid file system specified on $line" ;;
265209513Simp      esac
266209513Simp
267209513Simp      # Check that we have a valid size number
268209513Simp      expr $SIZE + 1 >/dev/null 2>/dev/null
269220059Sjpaetzel      if [ $? -ne 0 ]; then
270209513Simp        exit_err "ERROR: The size specified on $line is invalid"
271209513Simp      fi
272209513Simp
273209513Simp      # Check that the mount-point starts with /
274220059Sjpaetzel      echo "$MNT" | grep -qe "^/" -e "^none" 2>/dev/null
275220059Sjpaetzel      if [ $? -ne 0 ]; then
276209513Simp        exit_err "ERROR: The mount-point specified on $line is invalid"
277209513Simp      fi
278209513Simp
279209513Simp      if [ "$SIZE" = "0" ]
280209513Simp      then
281240315Sjpaetzel	if [ $USEDAUTOSIZE -eq 1 ] ; then
282240315Sjpaetzel          exit_err "ERROR: You can not have two partitions with a size of 0 specified!"
283240315Sjpaetzel	fi
284240315Sjpaetzel        case ${_pType} in
285240315Sjpaetzel	  gpt|apm) get_autosize "${_dTag}" "$_pDisk" ;;
286240315Sjpaetzel	        *) get_autosize "${_dTag}" "$_wSlice" ;;
287240315Sjpaetzel        esac
288240315Sjpaetzel        SOUT="-s ${VAL}M"
289240315Sjpaetzel	USEDAUTOSIZE=1
290209513Simp      else
291209513Simp        SOUT="-s ${SIZE}M"
292209513Simp      fi
293209513Simp
294209513Simp      # Check if we found a valid root partition
295209513Simp      check_for_mount "${MNT}" "/"
296220059Sjpaetzel      if [ $? -eq 0 ] ; then
297220059Sjpaetzel        export FOUNDROOT="1"
298217229Sjpaetzel        if [ "${CURPART}" = "2" -a "$_pType" = "gpt" ] ; then
299220059Sjpaetzel          export FOUNDROOT="0"
300209513Simp        fi
301235447Sjpaetzel        if [ "${CURPART}" = "3" -a "$_pType" = "apm" ] ; then
302235447Sjpaetzel          export FOUNDROOT="0"
303235447Sjpaetzel        fi
304217229Sjpaetzel        if [ "${CURPART}" = "1" -a "$_pType" = "mbr" ] ; then
305220059Sjpaetzel          export FOUNDROOT="0"
306217229Sjpaetzel        fi
307232415Sjpaetzel        if [ "${CURPART}" = "1" -a "$_pType" = "gptslice" ] ; then
308232415Sjpaetzel          export FOUNDROOT="0"
309232415Sjpaetzel        fi
310209513Simp      fi
311209513Simp
312209513Simp      check_for_mount "${MNT}" "/boot"
313220059Sjpaetzel      if [ $? -eq 0 ] ; then
314220059Sjpaetzel        export USINGBOOTPART="0"
315217229Sjpaetzel        if [ "${CURPART}" != "2" -a "${_pType}" = "gpt" ] ; then
316209513Simp            exit_err "/boot partition must be first partition"
317209513Simp        fi
318235447Sjpaetzel        if [ "${CURPART}" != "3" -a "${_pType}" = "apm" ] ; then
319235447Sjpaetzel            exit_err "/boot partition must be first partition"
320235447Sjpaetzel        fi
321217229Sjpaetzel        if [ "${CURPART}" != "1" -a "${_pType}" = "mbr" ] ; then
322217229Sjpaetzel            exit_err "/boot partition must be first partition"
323217229Sjpaetzel        fi
324232415Sjpaetzel        if [ "${CURPART}" != "1" -a "${_pType}" = "gptslice" ] ; then
325232415Sjpaetzel            exit_err "/boot partition must be first partition"
326232415Sjpaetzel        fi
327217229Sjpaetzel
328217229Sjpaetzel        if [ "${FS}" != "UFS" -a "${FS}" != "UFS+S" -a "${FS}" != "UFS+J" -a "${FS}" != "UFS+SUJ" ] ; then
329217229Sjpaetzel          exit_err "/boot partition must be formatted with UFS"
330217229Sjpaetzel        fi
331209513Simp      fi
332209513Simp
333209513Simp      # Generate a unique label name for this mount
334209513Simp      gen_glabel_name "${MNT}" "${FS}"
335209513Simp      PLABEL="${VAL}"
336209513Simp
337209513Simp      # Get any extra options for this fs / line
338217229Sjpaetzel      if [ "${_pType}" = "gpt" ] ; then
339217229Sjpaetzel        get_fs_line_xvars "${_pDisk}p${CURPART}" "${STRING}"
340235447Sjpaetzel      elif [ "${_pType}" = "apm" ] ; then
341235447Sjpaetzel        get_fs_line_xvars "${_pDisk}s${CURPART}" "${STRING}"
342217229Sjpaetzel      else
343227219Sjpaetzel        get_fs_line_xvars "${_wSlice}${PARTLETTER}" "${STRING}"
344217229Sjpaetzel      fi
345235445Sjpaetzel      XTRAOPTS="$VAR"
346209513Simp
347209513Simp      # Check if using zfs mirror
348235445Sjpaetzel      echo ${XTRAOPTS} | grep -q -e "mirror" -e "raidz"
349225657Sjpaetzel      if [ $? -eq 0 -a "$FS" = "ZFS" ] ; then
350232415Sjpaetzel        if [ "${_pType}" = "gpt" -o "${_pType}" = "gptslice" ] ; then
351217229Sjpaetzel       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}p${CURPART}")
352235447Sjpaetzel        elif [ "${_pType}" = "apm" ] ; then
353235447Sjpaetzel       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}s${CURPART}")
354217229Sjpaetzel        else
355235445Sjpaetzel       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_wSlice}${PARTLETTER}")
356217229Sjpaetzel        fi
357209513Simp      fi
358209513Simp
359209513Simp      # Figure out the gpart type to use
360209513Simp      case ${FS} in
361211730Simp        ZFS) PARTYPE="freebsd-zfs" ;;
362211730Simp        SWAP) PARTYPE="freebsd-swap" ;;
363211730Simp        *) PARTYPE="freebsd-ufs" ;;
364209513Simp      esac
365209513Simp
366209513Simp      # Create the partition
367217229Sjpaetzel      if [ "${_pType}" = "gpt" ] ; then
368217229Sjpaetzel	if [ "$CURPART" = "2" ] ; then
369217229Sjpaetzel	  # If this is GPT, make sure first partition is aligned to 4k
370232415Sjpaetzel          sleep 2
371233226Sjpaetzel          rc_halt "gpart add -a 4k ${SOUT} -t ${PARTYPE} ${_pDisk}"
372217229Sjpaetzel	else
373232415Sjpaetzel          sleep 2
374217229Sjpaetzel          rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_pDisk}"
375217229Sjpaetzel	fi
376232415Sjpaetzel      elif [ "${_pType}" = "gptslice" ]; then
377232415Sjpaetzel        sleep 2
378232415Sjpaetzel        rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_wSlice}"
379235447Sjpaetzel      elif [ "${_pType}" = "apm" ]; then
380235447Sjpaetzel        sleep 2
381235447Sjpaetzel        rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_pDisk}"
382217229Sjpaetzel      else
383232415Sjpaetzel        sleep 2
384217229Sjpaetzel        rc_halt "gpart add ${SOUT} -t ${PARTYPE} -i ${CURPART} ${_wSlice}"
385217229Sjpaetzel      fi
386209513Simp
387209513Simp      # Check if this is a root / boot partition, and stamp the right loader
388209513Simp      for TESTMNT in `echo ${MNT} | sed 's|,| |g'`
389209513Simp      do
390209513Simp        if [ "${TESTMNT}" = "/" -a -z "${BOOTTYPE}" ] ; then
391209513Simp           BOOTTYPE="${PARTYPE}" 
392209513Simp        fi 
393209513Simp        if [ "${TESTMNT}" = "/boot" ]  ; then
394209513Simp           BOOTTYPE="${PARTYPE}" 
395209513Simp        fi 
396209513Simp      done 
397209513Simp
398209513Simp      # Save this data to our partition config dir
399217229Sjpaetzel      if [ "${_pType}" = "gpt" ] ; then
400220909Sjpaetzel	_dFile="`echo $_pDisk | sed 's|/|-|g'`"
401233224Sjpaetzel        echo "${FS}#${MNT}#${ENC}#${PLABEL}#GPT#${XTRAOPTS}" >${PARTDIR}/${_dFile}p${CURPART}
402209513Simp
403217229Sjpaetzel        # Clear out any headers
404217229Sjpaetzel        sleep 2
405220059Sjpaetzel        dd if=/dev/zero of=${_pDisk}p${CURPART} count=2048 2>/dev/null
406209513Simp
407217229Sjpaetzel        # If we have a enc password, save it as well
408220059Sjpaetzel        if [ -n "${ENCPASS}" ] ; then
409220909Sjpaetzel          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}p${CURPART}-encpass
410217229Sjpaetzel        fi
411235447Sjpaetzel      elif [ "${_pType}" = "apm" ] ; then
412235447Sjpaetzel	_dFile="`echo $_pDisk | sed 's|/|-|g'`"
413235447Sjpaetzel        echo "${FS}#${MNT}#${ENC}#${PLABEL}#GPT#${XTRAOPTS}" >${PARTDIR}/${_dFile}s${CURPART}
414235447Sjpaetzel
415235447Sjpaetzel        # Clear out any headers
416235447Sjpaetzel        sleep 2
417235447Sjpaetzel        dd if=/dev/zero of=${_pDisk}s${CURPART} count=2048 2>/dev/null
418235447Sjpaetzel
419235447Sjpaetzel        # If we have a enc password, save it as well
420235447Sjpaetzel        if [ -n "${ENCPASS}" ] ; then
421235447Sjpaetzel          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}s${CURPART}-encpass
422235447Sjpaetzel        fi
423217229Sjpaetzel      else
424232415Sjpaetzel	# MBR Partition or GPT slice
425220909Sjpaetzel	_dFile="`echo $_wSlice | sed 's|/|-|g'`"
426233224Sjpaetzel        echo "${FS}#${MNT}#${ENC}#${PLABEL}#MBR#${XTRAOPTS}#${IMAGE}" >${PARTDIR}/${_dFile}${PARTLETTER}
427217229Sjpaetzel        # Clear out any headers
428217229Sjpaetzel        sleep 2
429220059Sjpaetzel        dd if=/dev/zero of=${_wSlice}${PARTLETTER} count=2048 2>/dev/null
430217229Sjpaetzel
431217229Sjpaetzel        # If we have a enc password, save it as well
432220059Sjpaetzel        if [ -n "${ENCPASS}" ] ; then
433220909Sjpaetzel          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}${PARTLETTER}-encpass
434217229Sjpaetzel        fi
435209513Simp      fi
436209513Simp
437217229Sjpaetzel
438209513Simp      # Increment our parts counter
439235447Sjpaetzel      if [ "$_pType" = "gpt" -o "$_pType" = "apm" ] ; then 
440220059Sjpaetzel          CURPART=$((CURPART+1))
441235447Sjpaetzel        # If this is a gpt/apm partition, 
442235447Sjpaetzel        # we can continue and skip the MBR part letter stuff
443217229Sjpaetzel        continue
444217229Sjpaetzel      else
445220059Sjpaetzel          CURPART=$((CURPART+1))
446217229Sjpaetzel        if [ "$CURPART" = "3" ] ; then CURPART="4" ; fi
447217229Sjpaetzel      fi
448209513Simp
449217229Sjpaetzel
450217229Sjpaetzel      # This partition letter is used, get the next one
451217229Sjpaetzel      case ${PARTLETTER} in
452217229Sjpaetzel        a) PARTLETTER="b" ;;
453217229Sjpaetzel        b) PARTLETTER="d" ;;
454217229Sjpaetzel        d) PARTLETTER="e" ;;
455217229Sjpaetzel        e) PARTLETTER="f" ;;
456217229Sjpaetzel        f) PARTLETTER="g" ;;
457217229Sjpaetzel        g) PARTLETTER="h" ;;
458217229Sjpaetzel        h) PARTLETTER="ERR" ;;
459217229Sjpaetzel        *) exit_err "ERROR: bsdlabel only supports up to letter h for partitions." ;;
460217229Sjpaetzel      esac
461217229Sjpaetzel
462209513Simp    fi # End of subsection locating a slice in config
463209513Simp
464220059Sjpaetzel    echo $line | grep -q "^commitDiskLabel" 2>/dev/null
465220059Sjpaetzel    if [ $? -eq 0 -a "${FOUNDPARTS}" = "0" ]
466209513Simp    then
467209513Simp
468209513Simp      # If this is the boot disk, stamp the right gptboot
469217229Sjpaetzel      if [ ! -z "${BOOTTYPE}" -a "$_pType" = "gpt" ] ; then
470209513Simp        case ${BOOTTYPE} in
471217229Sjpaetzel          freebsd-ufs) rc_halt "gpart bootcode -p /boot/gptboot -i 1 ${_pDisk}" ;;
472217229Sjpaetzel          freebsd-zfs) rc_halt "gpart bootcode -p /boot/gptzfsboot -i 1 ${_pDisk}" ;;
473209513Simp        esac 
474209513Simp      fi
475209513Simp
476217229Sjpaetzel      # Make sure to stamp the MBR loader
477217229Sjpaetzel      if [ "$_pType" = "mbr" ] ; then
478217229Sjpaetzel	rc_halt "gpart bootcode -b /boot/boot ${_wSlice}"
479217229Sjpaetzel      fi
480209513Simp
481209513Simp      # Found our flag to commit this label setup, check that we found at least 1 partition
482233224Sjpaetzel      if [ "${CURPART}" = "1" ] ; then
483209513Simp        exit_err "ERROR: commitDiskLabel was called without any partition entries for it!"
484209513Simp      fi
485209513Simp
486209513Simp      break
487209513Simp    fi
488209513Simp  done <${CFGF}
489209513Simp};
490209513Simp
491209513Simp# Reads through the config and sets up a BSDLabel for the given slice
492209513Simppopulate_disk_label()
493209513Simp{
494209513Simp  if [ -z "${1}" ]
495209513Simp  then
496209513Simp    exit_err "ERROR: populate_disk_label() called without argument!"
497209513Simp  fi
498209513Simp
499209513Simp  # Set some vars from the given working slice
500220909Sjpaetzel  diskid="`echo $1 | cut -d ':' -f 1`" 
501220909Sjpaetzel  disk="`echo $1 | cut -d ':' -f 1 | sed 's|-|/|g'`" 
502220909Sjpaetzel  slicenum="`echo $1 | cut -d ':' -f 2`" 
503220909Sjpaetzel  type="`echo $1 | cut -d ':' -f 3`" 
504209513Simp  
505209513Simp  # Set WRKSLICE based upon format we are using
506209513Simp  if [ "$type" = "mbr" ] ; then
507220909Sjpaetzel    wrkslice="${diskid}s${slicenum}"
508209513Simp  fi
509235447Sjpaetzel  if [ "$type" = "apm" ] ; then
510235447Sjpaetzel    wrkslice="${diskid}s${slicenum}"
511235447Sjpaetzel  fi
512232415Sjpaetzel  if [ "$type" = "gpt" -o "$type" = "gptslice" ] ; then
513220909Sjpaetzel    wrkslice="${diskid}p${slicenum}"
514209513Simp  fi
515209513Simp
516220909Sjpaetzel  if [ ! -e "${SLICECFGDIR}/${wrkslice}" ] ; then
517209513Simp    exit_err "ERROR: Missing SLICETAG data. This shouldn't happen - please let the developers know"
518209513Simp  fi
519209513Simp
520220909Sjpaetzel  disktag="`cat ${SLICECFGDIR}/${wrkslice}`"
521220909Sjpaetzel  slicedev="`echo $wrkslice | sed 's|-|/|g'`"
522220909Sjpaetzel  
523217229Sjpaetzel  # Setup the partitions with gpart
524220909Sjpaetzel  setup_gpart_partitions "${disktag}" "${disk}" "${slicedev}" "${slicenum}" "${type}"
525209513Simp
526209513Simp};
527209513Simp
528209513Simp# Function which reads in the disk slice config, and performs it
529209513Simpsetup_disk_label()
530209513Simp{
531209513Simp  # We are ready to start setting up the label, lets read the config and do the actions
532209513Simp  # First confirm that we have a valid WORKINGSLICES
533213650Simp  if [ -z "${WORKINGSLICES}" ]; then
534209513Simp    exit_err "ERROR: No slices were setup! Please report this to the maintainers"
535209513Simp  fi
536209513Simp
537209513Simp  # Check that the slices we have did indeed get setup and gpart worked
538209513Simp  for i in $WORKINGSLICES
539209513Simp  do
540209513Simp    disk="`echo $i | cut -d '-' -f 1`" 
541209513Simp    pnum="`echo $i | cut -d '-' -f 2`" 
542209513Simp    type="`echo $i | cut -d '-' -f 3`" 
543220909Sjpaetzel    if [ "$type" = "mbr" -a ! -e "${disk}s${pnum}" ] ; then
544209513Simp      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
545209513Simp    fi
546220909Sjpaetzel    if [ "$type" = "gpt" -a ! -e "${disk}p${pnum}" ] ; then
547209513Simp      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
548209513Simp    fi
549235447Sjpaetzel    if [ "$type" = "apm" -a ! -e "${disk}s${pnum}" ] ; then
550235447Sjpaetzel      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
551235447Sjpaetzel    fi
552232415Sjpaetzel    if [ "$type" = "gptslice" -a ! -e "${disk}p${pnum}" ] ; then
553232415Sjpaetzel      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
554232415Sjpaetzel    fi
555209513Simp  done
556209513Simp
557209513Simp  # Setup some files which we'll be referring to
558220059Sjpaetzel  export LABELLIST="${TMPDIR}/workingLabels"
559209513Simp  rm $LABELLIST >/dev/null 2>/dev/null
560209513Simp
561209513Simp  # Set our flag to determine if we've got a valid root partition in this setup
562220059Sjpaetzel  export FOUNDROOT="-1"
563209513Simp
564209513Simp  # Check if we are using a /boot partition
565220059Sjpaetzel  export USINGBOOTPART="1"
566209513Simp 
567209513Simp  # Set encryption on root check
568220059Sjpaetzel  export USINGENCROOT="1"
569209513Simp  
570209513Simp  # Make the tmp directory where we'll store FS info & mount-points
571209513Simp  rm -rf ${PARTDIR} >/dev/null 2>/dev/null
572209513Simp  mkdir -p ${PARTDIR} >/dev/null 2>/dev/null
573209513Simp  rm -rf ${PARTDIR}-enc >/dev/null 2>/dev/null
574209513Simp  mkdir -p ${PARTDIR}-enc >/dev/null 2>/dev/null
575209513Simp
576209513Simp  for i in $WORKINGSLICES
577209513Simp  do
578209513Simp    populate_disk_label "${i}"
579209513Simp  done
580209513Simp
581209513Simp  # Check if we made a root partition
582209513Simp  if [ "$FOUNDROOT" = "-1" ]
583209513Simp  then
584209513Simp    exit_err "ERROR: No root (/) partition specified!!"
585209513Simp  fi
586209513Simp
587209513Simp  # Check if we made a root partition
588209513Simp  if [ "$FOUNDROOT" = "1" -a "${USINGBOOTPART}" != "0" ]
589209513Simp  then
590209513Simp    exit_err "ERROR: (/) partition isn't first partition on disk!"
591209513Simp  fi
592209513Simp
593209513Simp  if [ "${USINGENCROOT}" = "0" -a "${USINGBOOTPART}" != "0" ]
594209513Simp  then
595209513Simp    exit_err "ERROR: Can't encrypt (/) with no (/boot) partition!"
596209513Simp  fi
597209513Simp};
598209513Simp
599212337Simpcheck_fstab_mbr()
600212337Simp{
601212337Simp  local SLICE
602212337Simp  local FSTAB
603212337Simp
604212337Simp  if [ -z "$2" ]
605212337Simp  then
606212337Simp	return 1
607212337Simp  fi
608212337Simp
609212337Simp  SLICE="$1"
610212337Simp  FSTAB="$2/etc/fstab"
611212337Simp
612212337Simp  if [ -f "${FSTAB}" ]
613212337Simp  then
614212337Simp    PARTLETTER=`echo "$SLICE" | sed -E 's|^.+([a-h])$|\1|'`
615212337Simp
616220059Sjpaetzel    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/$' 2>&1
617220059Sjpaetzel    if [ $? -eq 0 ]
618212337Simp    then
619212337Simp      if [ "${PARTLETTER}" = "a" ]
620212337Simp      then
621212337Simp        FOUNDROOT="0"
622212337Simp      else
623212337Simp        FOUNDROOT="1"
624212337Simp      fi
625213650Simp
626213650Simp      ROOTIMAGE="1"
627213650Simp
628212337Simp      export FOUNDROOT
629213650Simp      export ROOTIMAGE
630212337Simp    fi
631212337Simp
632220059Sjpaetzel    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/boot$' 2>&1
633220059Sjpaetzel    if [ $? -eq 0 ]
634212337Simp    then
635212337Simp      if [ "${PARTLETTER}" = "a" ]
636212337Simp      then
637212337Simp        USINGBOOTPART="0"
638212337Simp      else 
639212337Simp        exit_err "/boot partition must be first partition"
640212337Simp      fi 
641212337Simp      export USINGBOOTPART
642212337Simp    fi
643212337Simp
644212337Simp    return 0
645212337Simp  fi
646212337Simp
647212337Simp  return 1
648212337Simp};
649212337Simp
650212337Simpcheck_fstab_gpt()
651212337Simp{
652212337Simp  local SLICE
653212337Simp  local FSTAB
654212337Simp
655212337Simp  if [ -z "$2" ]
656212337Simp  then
657212337Simp	return 1
658212337Simp  fi
659212337Simp
660212337Simp  SLICE="$1"
661212337Simp  FSTAB="$2/etc/fstab"
662212337Simp
663212337Simp  if [ -f "${FSTAB}" ]
664212337Simp  then
665212337Simp    PARTNUMBER=`echo "${SLICE}" | sed -E 's|^.+p([0-9]*)$|\1|'`
666212337Simp
667220059Sjpaetzel    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/$' 2>&1
668220059Sjpaetzel    if [ $? -eq 0 ]
669212337Simp    then
670212337Simp      if [ "${PARTNUMBER}" = "2" ]
671212337Simp      then
672212337Simp        FOUNDROOT="0"
673212337Simp      else
674212337Simp        FOUNDROOT="1"
675212337Simp      fi
676213650Simp
677213650Simp      ROOTIMAGE="1"
678213650Simp
679212337Simp      export FOUNDROOT
680213650Simp      export ROOTIMAGE
681212337Simp    fi
682212337Simp
683220059Sjpaetzel    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/boot$' 2>&1
684220059Sjpaetzel    if [ $? -eq 0 ]
685212337Simp    then
686212337Simp      if [ "${PARTNUMBER}" = "2" ]
687212337Simp      then
688212337Simp        USINGBOOTPART="0"
689212337Simp      else 
690212337Simp        exit_err "/boot partition must be first partition"
691212337Simp      fi 
692212337Simp      export USINGBOOTPART
693212337Simp    fi
694212337Simp
695212337Simp    return 0
696212337Simp  fi
697212337Simp
698212337Simp
699212337Simp  return 1
700212337Simp};
701212337Simp
702213650Simpcheck_disk_layout()
703212337Simp{
704212337Simp  local SLICES
705212337Simp  local TYPE
706213650Simp  local DISK
707212337Simp  local RES
708212337Simp  local F
709212337Simp
710213650Simp  DISK="$1"
711212337Simp  TYPE="MBR"
712212337Simp
713213650Simp  if [ -z "${DISK}" ]
714212337Simp  then
715212337Simp	return 1
716212337Simp  fi
717212337Simp
718213650Simp  SLICES_MBR=`ls /dev/${DISK}s[1-4]*[a-h]* 2>/dev/null`
719213650Simp  SLICES_GPT=`ls /dev/${DISK}p[0-9]* 2>/dev/null`
720213650Simp  SLICES_SLICE=`ls /dev/${DISK}[a-h]* 2>/dev/null`
721213650Simp
722213650Simp  if [ -n "${SLICES_MBR}" ]
723212337Simp  then
724213650Simp    SLICES="${SLICES_MBR}"
725213650Simp    TYPE="MBR"
726213650Simp    RES=0
727212337Simp  fi
728213650Simp  if [ -n "${SLICES_GPT}" ]
729212337Simp  then
730213650Simp    SLICES="${SLICES_GPT}"
731213650Simp    TYPE="GPT"
732212337Simp    RES=0
733212337Simp  fi
734213650Simp  if [ -n "${SLICES_SLICE}" ]
735213650Simp  then
736213650Simp    SLICES="${SLICES_SLICE}"
737213650Simp    TYPE="MBR"
738213650Simp    RES=0
739213650Simp  fi
740213650Simp  
741212337Simp  for slice in ${SLICES}
742212337Simp  do
743212337Simp    F=1
744212337Simp    mount ${slice} /mnt 2>/dev/null
745220059Sjpaetzel    if [ $? -ne 0 ]
746212337Simp    then
747212337Simp      continue
748212337Simp    fi 
749212337Simp
750212337Simp    if [ "${TYPE}" = "MBR" ]
751212337Simp    then
752212337Simp	  check_fstab_mbr "${slice}" "/mnt"
753212337Simp      F="$?"
754212337Simp
755212337Simp    elif [ "${TYPE}" = "GPT" ]
756212337Simp    then
757212337Simp	  check_fstab_gpt "${slice}" "/mnt"
758212337Simp      F="$?"
759212337Simp    fi 
760212337Simp
761220059Sjpaetzel    if [ ${F} -eq 0 ]
762212337Simp    then
763212337Simp      umount /mnt
764212337Simp      break 
765212337Simp    fi
766212337Simp
767212337Simp    umount /mnt
768212337Simp  done
769212337Simp
770212337Simp  return ${RES}
771212337Simp};
772