1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "bootdata.h"
6 #include "util.h"
7 
8 #pragma GCC visibility push(hidden)
9 
10 #include <bootdata/decompress.h>
11 #include <zircon/boot/bootdata.h>
12 #include <zircon/syscalls.h>
13 #include <string.h>
14 
15 #pragma GCC visibility pop
16 
bootdata_get_bootfs(zx_handle_t log,zx_handle_t vmar_self,zx_handle_t bootdata_vmo)17 zx_handle_t bootdata_get_bootfs(zx_handle_t log, zx_handle_t vmar_self,
18                                 zx_handle_t bootdata_vmo) {
19     size_t off = 0;
20     for (;;) {
21         bootdata_t bootdata;
22         zx_status_t status = zx_vmo_read(bootdata_vmo, &bootdata,
23                                          off, sizeof(bootdata));
24         check(log, status, "zx_vmo_read failed on bootdata VMO");
25         if (!(bootdata.flags & BOOTDATA_FLAG_V2)) {
26             fail(log, "bootdata v1 no longer supported");
27         }
28 
29         switch (bootdata.type) {
30         case BOOTDATA_CONTAINER:
31             if (off == 0) {
32                 // Quietly skip container header.
33                 bootdata.length = 0;
34             } else {
35                 fail(log, "container in the middle of bootdata");
36             }
37             break;
38 
39         case BOOTDATA_BOOTFS_BOOT:;
40             const char* errmsg;
41             zx_handle_t bootfs_vmo;
42             status = decompress_bootdata(vmar_self, bootdata_vmo, off,
43                                          bootdata.length + sizeof(bootdata),
44                                          &bootfs_vmo, &errmsg);
45             check(log, status, "%s", errmsg);
46 
47             // Signal that we've already processed this one.
48             bootdata.type = BOOTDATA_BOOTFS_DISCARD;
49             check(log, zx_vmo_write(bootdata_vmo, &bootdata.type,
50                                     off + offsetof(bootdata_t, type),
51                                     sizeof(bootdata.type)),
52                   "zx_vmo_write failed on bootdata VMO\n");
53 
54             return bootfs_vmo;
55         }
56 
57         off += BOOTDATA_ALIGN(sizeof(bootdata) + bootdata.length);
58     }
59 
60     fail(log, "no '/boot' bootfs in bootstrap message\n");
61 }
62