1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #pragma once
8 
9 #define MEMMOV_OPS_DST_OFFSET (0)
10 #define MEMMOV_OPS_SRC_OFFSET (8)
11 #define MEMMOV_OPS_LEN_OFFSET (16)
12 
13 #ifndef __ASSEMBLER__
14 
15 #include <zircon/compiler.h>
16 #include <fbl/ref_ptr.h>
17 #include <vm/vm_object.h>
18 #include <zircon/types.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 // Warning: The geometry of this struct is depended upon by the mexec assembly
23 //          function. Do not modify without also updating mexec.S.
24 typedef struct __PACKED {
25     void* dst;
26     void* src;
27     size_t len;
28 } memmov_ops_t;
29 
30 // Implemented in assembly. Copies the new kernel into place and branches to it.
31 typedef void (*mexec_asm_func)(uint64_t arg0, uint64_t arg1, uint64_t arg2,
32                                uint64_t aux, memmov_ops_t* ops,
33                                void* new_kernel_addr);
34 
35 // Save the crashlog for propagation to the next kernel.
36 void mexec_stash_crashlog(fbl::RefPtr<VmObject> vmo);
37 
38 /* Allow the platform to patch the zbi structure with any platform specific
39  * data that might be necessary for the kernel that mexec is chain-loading.
40  */
41 zx_status_t platform_mexec_patch_zbi(uint8_t* bootdata, const size_t len);
42 
43 /* This function is called at the beginning of mexec.  Interrupts are not yet
44  * disabled, but only one CPU is running.
45  */
46 void platform_mexec_prep(uintptr_t new_bootimage_addr, size_t new_bootimage_len);
47 
48 /* Ask the platform to mexec into the next kernel.
49  * This function is called after platform_mexec_prep(), with interrupts disabled.
50  */
51 void platform_mexec(mexec_asm_func mexec_assembly, memmov_ops_t* ops,
52                     uintptr_t new_bootimage_addr, size_t new_bootimage_len,
53                     uintptr_t entry64_addr);
54 
55 static_assert(__offsetof(memmov_ops_t, dst) == MEMMOV_OPS_DST_OFFSET, "");
56 static_assert(__offsetof(memmov_ops_t, src) == MEMMOV_OPS_SRC_OFFSET, "");
57 static_assert(__offsetof(memmov_ops_t, len) == MEMMOV_OPS_LEN_OFFSET, "");
58 
59 #endif // __ASSEMBLER__
60