Merge lp:~newell-jensen/curtin/add-arm64-support into lp:~curtin-dev/curtin/trunk
- add-arm64-support
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 142 | ||||
Proposed branch: | lp:~newell-jensen/curtin/add-arm64-support | ||||
Merge into: | lp:~curtin-dev/curtin/trunk | ||||
Diff against target: |
324 lines (+114/-30) 3 files modified
curtin/commands/block_meta.py (+69/-14) curtin/commands/install.py (+5/-1) helpers/common (+40/-15) |
||||
To merge this branch: | bzr merge lp:~newell-jensen/curtin/add-arm64-support | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
curtin developers | Pending | ||
Review via email: mp+226196@code.launchpad.net |
Commit message
Add arm64 support to curtin. This branch also adds support to allow the creation of an extra /boot partition that is often times needed by arm64 boot loaders.
Description of the change
Andres Rodriguez (andreserl) wrote : | # |
Blake Rouse (blake-rouse) wrote : | # |
I made some comments on the code. I know its a work in-progress. I didn't comment much on the bash code, as I do not have that much experience.
Jason Hobbs (jason-hobbs) wrote : | # |
You can check for the '/sys/firmware/efi' directory. If it exists, then the system was booted with UEFI, not U-Boot, and doesn't require the separate boot partition. It's my understanding that arm64/generic systems booting UEFI won't require the separate /boot partition, but we would need to confirm this with the vendor. I would expect that UEFI will be able to handle either scenario - separate boot partition or not.
I have a few comments inline below too.
Scott Moser (smoser) wrote : | # |
I'll take a look further next week,
but some nitpick comments inline.
make sure you follow the code conventions in tools/common (4 space indentation).
Newell Jensen (newell-jensen) wrote : | # |
Scott,
There was a newer revision checked in last night but you commented on the
old revision. Looking over your comments. As far as tabs, I am using
emacs and it is using 4-spaces so your comment on the tab indentation seems
odd and I have checked the file and everything lines up so maybe launchpad
shows it like that? I will update branch and push so you can have a look
at it on Monday.
On Fri, Jul 18, 2014 at 6:05 AM, Scott Moser <email address hidden> wrote:
> I'll take a look further next week,
> but some nitpick comments inline.
>
> make sure you follow the code conventions in tools/common (4 space
> indentation).
>
>
> Diff comments:
>
> > === modified file 'curtin/
> > --- curtin/
> > +++ curtin/
> > @@ -32,7 +32,7 @@
> > 'metavar': 'DEVICE', 'default': None, }),
> > ('--fstype', {'help': 'root filesystem type',
> > 'choices': ['ext4', 'ext3'], 'default': 'ext4'}),
> > - ('mode', {'help': 'meta-mode to use', 'choices': ['raid0',
> 'simple']}),
> > + ('mode', {'help': 'meta-mode to use', 'choices': ['raid0',
> 'simple', 'simple-boot']}),
> > )
> > )
> >
> > @@ -41,6 +41,8 @@
> > # main entry point for the block-meta command.
> > if args.mode == "simple":
> > meta_simple(args)
> > + elif args.mode == "simple-boot":
> > + meta_simple_
> > else:
> > raise NotImplementedE
> args.mode)
> >
> > @@ -131,6 +133,80 @@
> > return 0
> >
> >
> > +def meta_simple_
> > + """Similar to meta_simple but it also creates an extra /boot
> partition.
> > + This is needed from some instances of u-boot.
> > + """
> > + state = util.load_
> > +
> > + cfg = util.load_
> > +
> > + devices = args.devices
> > + if devices is None:
> > + devices = cfg.get(
> > +
> > + # Remove duplicates but maintain ordering.
> > + devices = list(OrderedDic
> > +
> > + if len(devices) == 0:
> > + devices = block.get_
> > + LOG.warn(
> devices)
> > +
> > + if len(devices) > 1:
> > + if args.devices is not None:
> > + LOG.warn(
> > + "using first found")
> > + available = [f for f in devices
> > + if block.is_
> > + target = sorted(
> > + LOG.warn("mode is 'simple-boot'. multiple devices given. using
> '%s' "
> > + "(first available)", target)
> > + else:
> > + target = devices[0]
> > +
> > + if not block.is_
> > + raise Exception("target device '%s' is not a valid device" %
> target)
> > +
> > + (devname, devnode) = block.get_
> > +
> > + LOG.info(
> > +
> > + sources = cfg.get('source...
- 145. By Newell Jensen
-
Added comments to common to help in readability and deleted some unused code.
Newell Jensen (newell-jensen) wrote : | # |
Scott,
I am no bash expert so you might be correct that maxend might be "" but since I am setting it by doing:
Won't it be something other than "" for sure?
Scott Moser (smoser) wrote : | # |
you most certainly added tabs.
Newell Jensen (newell-jensen) wrote : | # |
Yes, I did. Originally mis-read what you wrote. Will fix that.
On Mon, Jul 21, 2014 at 9:57 AM, Scott Moser <email address hidden> wrote:
> you most certainly added tabs.
>
> --
>
> https:/
> You are the owner of lp:~newell-jensen/curtin/add-arm64-support.
>
- 146. By Newell Jensen
-
Replacing tabs with spaces.
Scott Moser (smoser) wrote : | # |
comments remaining:
- if user specifies 'simple-boot', but is_uefi_bootable, they will get uefi. that seems possibly wrong
- boot is passed around in helpers/common as a number. makes more sense to be a boolean, no? use 'true' or 'false' as values.
- i dont think i like having partitioning_
I think i'd rather just have 'simple' do the right thing, but let a user provided config explicitly set that.
Also, config can be set on the command line, so:
curtin install --set block-meta/
is the same as you have here with:
curtin block-meta --boot
I've just proposed merging:
bzr+ssh:
into here. It has some cleanups. the config based approach isn't completely done there.
- 147. By Newell Jensen
-
Merging Scott Moser's changes in my branch.
- 148. By Newell Jensen
-
Added /boot partition support to UEFI.
- 149. By Newell Jensen
-
Deleted UEFI /boot partition capabilities. Stripped /boot size, sticking with
default of 512MiB. Created AUTO mode that will check for platform machine
architecture. - 150. By Newell Jensen
-
Deleting AUTO mode to simplify things and move all the logic in block_meta.py
Preview Diff
1 | === modified file 'curtin/commands/block_meta.py' |
2 | --- curtin/commands/block_meta.py 2014-07-21 17:07:39 +0000 |
3 | +++ curtin/commands/block_meta.py 2014-07-22 21:12:03 +0000 |
4 | @@ -22,24 +22,32 @@ |
5 | |
6 | from . import populate_one_subcmd |
7 | |
8 | +import os |
9 | +import platform |
10 | + |
11 | +SIMPLE = 'simple' |
12 | +SIMPLE_BOOT = 'simple-boot' |
13 | |
14 | CMD_ARGUMENTS = ( |
15 | ((('-D', '--devices'), |
16 | {'help': 'which devices to operate on', 'action': 'append', |
17 | 'metavar': 'DEVICE', 'default': None, }), |
18 | - ('--fstype', {'help': 'root filesystem type', |
19 | + ('--fstype', {'help': 'root partition filesystem type', |
20 | 'choices': ['ext4', 'ext3'], 'default': 'ext4'}), |
21 | - ('mode', {'help': 'meta-mode to use', 'choices': ['raid0', 'simple']}), |
22 | + ('--boot-fstype', {'help': 'boot partition filesystem type', |
23 | + 'choices': ['ext4', 'ext3'], 'default': None}), |
24 | + ('mode', {'help': 'meta-mode to use', |
25 | + 'choices': ['raid0', SIMPLE, SIMPLE_BOOT]}), |
26 | ) |
27 | ) |
28 | |
29 | |
30 | def block_meta(args): |
31 | # main entry point for the block-meta command. |
32 | - if args.mode == "simple": |
33 | + if args.mode in (SIMPLE, SIMPLE_BOOT): |
34 | meta_simple(args) |
35 | else: |
36 | - raise NotImplementedError("mode=%s is not implemenbed" % args.mode) |
37 | + raise NotImplementedError("mode=%s is not implemented" % args.mode) |
38 | |
39 | |
40 | def logtime(msg, func, *args, **kwargs): |
41 | @@ -61,7 +69,30 @@ |
42 | return block.get_root_device([devname, ]) |
43 | |
44 | |
45 | +def get_bootpt_cfg(cfg, enabled=False, fstype=None): |
46 | + # 'cfg' looks like: |
47 | + # enabled: boolean |
48 | + # fstype: filesystem type (default to 'fstype') |
49 | + # label: filesystem label (default to 'boot') |
50 | + # size: filesystem size in M (default to 512) |
51 | + # parm enable can enable, but not disable |
52 | + # parm fstype overrides cfg['fstype'] |
53 | + def_boot = platform.machine() in ('aarch64') |
54 | + ret = {'enabled': def_boot, 'fstype': None, 'size': 512, 'label': 'boot'} |
55 | + ret.update(cfg) |
56 | + if enabled: |
57 | + ret['enabled'] = True |
58 | + if ret['enabled']: |
59 | + if fstype and not ret['fstype']: |
60 | + ret['fstype'] = fstype |
61 | + ret['size'] = int(ret['size']) |
62 | + return ret |
63 | + |
64 | + |
65 | def meta_simple(args): |
66 | + """Creates a root partition. If args.mode == SIMPLE_BOOT, it will also |
67 | + create a separate /boot partition. |
68 | + """ |
69 | state = util.load_command_environment() |
70 | |
71 | cfg = util.load_command_config(args, state) |
72 | @@ -70,22 +101,27 @@ |
73 | if devices is None: |
74 | devices = cfg.get('block-meta', {}).get('devices', []) |
75 | |
76 | + bootpt = get_bootpt_cfg( |
77 | + cfg.get('block-meta', {}).get('boot-partition', {}), |
78 | + enabled=args.mode == SIMPLE_BOOT, fstype=args.boot_fstype) |
79 | + |
80 | # Remove duplicates but maintain ordering. |
81 | devices = list(OrderedDict.fromkeys(devices)) |
82 | |
83 | if len(devices) == 0: |
84 | devices = block.get_installable_blockdevs() |
85 | - LOG.warn("simple mode, no devices given. unused list: %s", devices) |
86 | + LOG.warn("'%s' mode, no devices given. unused list: %s", |
87 | + (args.mode, devices)) |
88 | |
89 | if len(devices) > 1: |
90 | if args.devices is not None: |
91 | - LOG.warn("simple mode but multiple devices given. " |
92 | - "using first found") |
93 | + LOG.warn("'%s' mode but multiple devices given. " |
94 | + "using first found", args.mode) |
95 | available = [f for f in devices |
96 | if block.is_valid_device(f)] |
97 | target = sorted(available)[0] |
98 | - LOG.warn("mode is 'simple'. multiple devices given. using '%s' " |
99 | - "(first available)", target) |
100 | + LOG.warn("mode is '%s'. multiple devices given. using '%s' " |
101 | + "(first available)", (args.mode, target)) |
102 | else: |
103 | target = devices[0] |
104 | |
105 | @@ -94,10 +130,11 @@ |
106 | |
107 | (devname, devnode) = block.get_dev_name_entry(target) |
108 | |
109 | - LOG.info("installing in simple mode to '%s'", devname) |
110 | + LOG.info("installing in '%s' mode to '%s'", (args.mode, devname)) |
111 | |
112 | sources = cfg.get('sources', {}) |
113 | dd_images = util.get_dd_images(sources) |
114 | + |
115 | if len(dd_images): |
116 | # we have at least one dd-able image |
117 | # we will only take the first one |
118 | @@ -110,19 +147,37 @@ |
119 | logtime( |
120 | "partition --format uefi %s" % devnode, |
121 | util.subp, ("partition", "--format", "uefi", devnode)) |
122 | + bootpt['enabled'] = False |
123 | + elif bootpt['enabled']: |
124 | + logtime("partition --boot %s" % devnode, |
125 | + util.subp, ("partition", "--boot", devnode)) |
126 | + bootdev = devnode + "1" |
127 | + rootdev = devnode + "2" |
128 | else: |
129 | logtime( |
130 | "partition %s" % devnode, |
131 | util.subp, ("partition", devnode)) |
132 | - |
133 | - rootdev = devnode + "1" |
134 | - |
135 | + rootdev = devnode + "1" |
136 | + |
137 | + # mkfs for root partition first and mount |
138 | cmd = ['mkfs.%s' % args.fstype, '-q', '-L', 'cloudimg-rootfs', rootdev] |
139 | logtime(' '.join(cmd), util.subp, cmd) |
140 | - |
141 | util.subp(['mount', rootdev, state['target']]) |
142 | |
143 | + if bootpt['enabled']: |
144 | + # create 'boot' directory in state['target'] |
145 | + boot_dir = os.path.join(state['target'], 'boot') |
146 | + util.subp(['mkdir', boot_dir]) |
147 | + # mkfs for boot partition and mount |
148 | + cmd = ['mkfs.%s' % bootpt['fstype'], |
149 | + '-q', '-L', bootpt['label'], bootdev] |
150 | + logtime(' '.join(cmd), util.subp, cmd) |
151 | + util.subp(['mount', bootdev, boot_dir]) |
152 | + |
153 | with open(state['fstab'], "w") as fp: |
154 | + if bootpt['enabled']: |
155 | + fp.write("LABEL=%s /boot %s defaults 0 0\n" % |
156 | + (bootpt['label'], bootpt['fstype'])) |
157 | fp.write("LABEL=%s / %s defaults 0 0\n" % |
158 | ('cloudimg-rootfs', args.fstype)) |
159 | |
160 | |
161 | === modified file 'curtin/commands/install.py' |
162 | --- curtin/commands/install.py 2014-06-08 13:52:36 +0000 |
163 | +++ curtin/commands/install.py 2014-07-22 21:12:03 +0000 |
164 | @@ -29,13 +29,15 @@ |
165 | |
166 | from . import populate_one_subcmd |
167 | |
168 | + |
169 | CONFIG_BUILTIN = { |
170 | 'sources': {}, |
171 | 'stages': ['early', 'partitioning', 'network', 'extract', 'curthooks', |
172 | 'hook', 'late'], |
173 | 'extract_commands': {'builtin': ['curtin', 'extract']}, |
174 | 'hook_commands': {'builtin': ['curtin', 'hook']}, |
175 | - 'partitioning_commands': {'builtin': ['curtin', 'block-meta', 'simple']}, |
176 | + 'partitioning_commands': { |
177 | + 'builtin': ['curtin', 'block-meta', 'simple']}, |
178 | 'curthooks_commands': {'builtin': ['curtin', 'curthooks']}, |
179 | 'late_commands': {'builtin': []}, |
180 | 'network_commands': {'builtin': ['curtin', 'net-meta', 'auto']}, |
181 | @@ -271,6 +273,8 @@ |
182 | finally: |
183 | for d in ('sys', 'dev', 'proc'): |
184 | util.do_umount(os.path.join(workingd.target, d)) |
185 | + if util.is_mounted(workingd.target, 'boot'): |
186 | + util.do_umount(os.path.join(workingd.target, 'boot')) |
187 | util.do_umount(workingd.target) |
188 | shutil.rmtree(workingd.top) |
189 | |
190 | |
191 | === modified file 'helpers/common' |
192 | --- helpers/common 2014-04-21 16:18:39 +0000 |
193 | +++ helpers/common 2014-07-22 21:12:03 +0000 |
194 | @@ -15,6 +15,7 @@ |
195 | -f | --format F use partition table format F. [mbr, gpt, uefi] |
196 | default gpt |
197 | -E | --end E end the partition at E (unit 1k bytes) |
198 | + -b | --boot create a boot partition (512 MiB - default) |
199 | EOF |
200 | [ $# -eq 0 ] || echo "$@" |
201 | } |
202 | @@ -60,8 +61,8 @@ |
203 | } |
204 | |
205 | pt_gpt() { |
206 | - local target="$1" end=${2:-""} size="" s512="" ptype="L" |
207 | - local start="2048" pt1size="" maxend="" |
208 | + local target="$1" end=${2:-""} boot="$3" size="" s512="" ptype="L" |
209 | + local start="2048" rootsize="" bootsize="1048576" maxend="" |
210 | local isblk=false |
211 | getsize "$target" || |
212 | { error "failed to get size of $target"; return 1; } |
213 | @@ -71,15 +72,33 @@ |
214 | else |
215 | end=$(($end/512)) |
216 | fi |
217 | - maxend=$((($size/512)-2048)) |
218 | + |
219 | + if [ "$boot" = true ]; then |
220 | + maxend=$((($size/512)-$start-$bootsize)) |
221 | + if [ $maxend -lt 0 ]; then |
222 | + error "Disk is not big enough for /boot partition on $target"; |
223 | + return 1; |
224 | + fi |
225 | + else |
226 | + maxend=$((($size/512)-$start)) |
227 | + fi |
228 | [ "$end" -gt "$maxend" ] && end="$maxend" |
229 | debug 1 "maxend=$maxend end=$end size=$size" |
230 | |
231 | [ -b "$target" ] && isblk=true |
232 | |
233 | - sgdisk --new "15:2048:+1M" --typecode=15:ef02 \ |
234 | - --new "1::$end" --typecode=1:8300 "$target" || |
235 | - { error "failed to gpt partition $target"; return 1; } |
236 | + if [ "$boot" = true ]; then |
237 | + # Creating 'efi', '/boot' and '/' partitions |
238 | + sgdisk --new "15:$start:+1M" --typecode=15:ef02 \ |
239 | + --new "1::+512M" --typecode=1:8300 \ |
240 | + --new "2::$end" --typecode=2:8300 "$target" || |
241 | + { error "failed to gpt partition $target"; return 1; } |
242 | + else |
243 | + # Creating 'efi' and '/' partitions |
244 | + sgdisk --new "15:$start:+1M" --typecode=15:ef02 \ |
245 | + --new "1::$end" --typecode=1:8300 "$target" || |
246 | + { error "failed to gpt partition $target"; return 1; } |
247 | + fi |
248 | |
249 | if $isblk; then |
250 | blockdev --rereadpt "$target" |
251 | @@ -88,12 +107,16 @@ |
252 | { error "no partition found ${target}1"; return 1; } |
253 | [ -b "${target}15" ] || |
254 | { error "no partition found ${target}15"; return 1; } |
255 | + if [ "$boot" = true ]; then |
256 | + [ -b "${target}2" ] || |
257 | + { error "no partition found ${target}2"; return 1; } |
258 | + fi |
259 | fi |
260 | } |
261 | |
262 | pt_uefi() { |
263 | local target="$1" end=${2:-""} size="" s512="" ptype="L" |
264 | - local start="2048" pt1size="" maxend="" |
265 | + local start="2048" rootsize="" maxend="" |
266 | local isblk=false |
267 | getsize "$target" || |
268 | { error "failed to get size of $target"; return 1; } |
269 | @@ -103,14 +126,15 @@ |
270 | else |
271 | end=$(($end/512)) |
272 | fi |
273 | - maxend=$((($size/512)-2048)) |
274 | + |
275 | + maxend=$((($size/512)-$start)) |
276 | [ "$end" -gt "$maxend" ] && end="$maxend" |
277 | debug 1 "maxend=$maxend end=$end size=$size" |
278 | |
279 | [ -b "$target" ] && isblk=true |
280 | |
281 | - # Part 15 is the UEFI partition, part 1 is root |
282 | - sgdisk --new "15:2048:+512M" --typecode=15:ef00 "$target" \ |
283 | + # Creating 'UEFI' and '/' partitions |
284 | + sgdisk --new "15:2048:+512M" --typecode=15:ef00 \ |
285 | --new "1::$end" --typecode=1:8300 "$target" || |
286 | { error "failed to sgdisk for uefi to $target"; return 1; } |
287 | |
288 | @@ -175,22 +199,23 @@ |
289 | } |
290 | |
291 | partition_main() { |
292 | - local short_opts="hE:f:v" |
293 | - local long_opts="help,end:,format:,verbose" |
294 | + local short_opts="hE:f:bv" |
295 | + local long_opts="help,end:,format:,boot,verbose" |
296 | local getopt_out=$(getopt --name "${0##*/}" \ |
297 | --options "${short_opts}" --long "${long_opts}" -- "$@") && |
298 | eval set -- "${getopt_out}" || |
299 | { partition_main_usage 1>&2; return 1; } |
300 | |
301 | local cur="" next="" |
302 | - local format="mbr" target="" end="" |
303 | + local format="gpt" boot=false target="" end="" |
304 | |
305 | while [ $# -ne 0 ]; do |
306 | cur="$1"; next="$2"; |
307 | case "$cur" in |
308 | -h|--help) partition_main_usage ; exit 0;; |
309 | + -E|--end) end=$next; shift;; |
310 | -f|--format) format=$next; shift;; |
311 | - -E|--end) end=$next; shift;; |
312 | + -b|--boot) boot=true;; |
313 | -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; |
314 | --) shift; break;; |
315 | esac |
316 | @@ -222,7 +247,7 @@ |
317 | if [ "$format" = "mbr" ]; then |
318 | pt_mbr "$target" "$end" |
319 | elif [ "$format" = "gpt" ]; then |
320 | - pt_gpt "$target" "$end"] |
321 | + pt_gpt "$target" "$end" "$boot" |
322 | elif [ "$format" = "uefi" ]; then |
323 | pt_uefi "$target" "$end" |
324 | fi |
What we need to consider here is that what happens in we are booting arm64/generic. Curtin will continue to see this as aarch64. This would mean that we probably won't need to do the partitioning here, as it only applies to u-boot, right?