1*d2670fc4SToomas Soome /*
2*d2670fc4SToomas Soome * This file and its contents are supplied under the terms of the
3*d2670fc4SToomas Soome * Common Development and Distribution License ("CDDL"), version 1.0.
4*d2670fc4SToomas Soome * You may only use this file in accordance with the terms of version
5*d2670fc4SToomas Soome * 1.0 of the CDDL.
6*d2670fc4SToomas Soome *
7*d2670fc4SToomas Soome * A full copy of the text of the CDDL should have accompanied this
8*d2670fc4SToomas Soome * source. A copy of the CDDL is also available via the Internet at
9*d2670fc4SToomas Soome * http://www.illumos.org/license/CDDL.
10*d2670fc4SToomas Soome */
11*d2670fc4SToomas Soome
12*d2670fc4SToomas Soome /*
13*d2670fc4SToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
14*d2670fc4SToomas Soome */
15*d2670fc4SToomas Soome
16*d2670fc4SToomas Soome /*
17*d2670fc4SToomas Soome * dboot module utility functions for multiboot 2 tags processing.
18*d2670fc4SToomas Soome */
19*d2670fc4SToomas Soome
20*d2670fc4SToomas Soome #include <sys/inttypes.h>
21*d2670fc4SToomas Soome #include <sys/param.h>
22*d2670fc4SToomas Soome #include <sys/systm.h>
23*d2670fc4SToomas Soome #include <sys/sysmacros.h>
24*d2670fc4SToomas Soome #include <sys/multiboot2.h>
25*d2670fc4SToomas Soome #include <sys/multiboot2_impl.h>
26*d2670fc4SToomas Soome
27*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx;
28*d2670fc4SToomas Soome
29*d2670fc4SToomas Soome typedef boolean_t (*dboot_multiboot2_iterate_cb_t)
30*d2670fc4SToomas Soome (int, multiboot_tag_t *, struct dboot_multiboot2_iterate_ctx *);
31*d2670fc4SToomas Soome
32*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx {
33*d2670fc4SToomas Soome dboot_multiboot2_iterate_cb_t dboot_iter_callback;
34*d2670fc4SToomas Soome int dboot_iter_index; /* item from set */
35*d2670fc4SToomas Soome uint32_t dboot_iter_tag; /* tag to search */
36*d2670fc4SToomas Soome multiboot_tag_t *dboot_iter_tagp; /* search result */
37*d2670fc4SToomas Soome };
38*d2670fc4SToomas Soome
39*d2670fc4SToomas Soome /*
40*d2670fc4SToomas Soome * Multiboot2 tag list elements are aligned to MULTIBOOT_TAG_ALIGN.
41*d2670fc4SToomas Soome * To get the next item from the list, we first add the tag's size
42*d2670fc4SToomas Soome * to the start of the current tag. Next, we round up that address to the
43*d2670fc4SToomas Soome * nearest MULTIBOOT_TAG_ALIGN address.
44*d2670fc4SToomas Soome */
45*d2670fc4SToomas Soome
46*d2670fc4SToomas Soome static multiboot_tag_t *
dboot_multiboot2_first_tag(multiboot2_info_header_t * mbi)47*d2670fc4SToomas Soome dboot_multiboot2_first_tag(multiboot2_info_header_t *mbi)
48*d2670fc4SToomas Soome {
49*d2670fc4SToomas Soome return (&mbi->mbi_tags[0]);
50*d2670fc4SToomas Soome }
51*d2670fc4SToomas Soome
52*d2670fc4SToomas Soome static multiboot_tag_t *
dboot_multiboot2_next_tag(multiboot_tag_t * tag)53*d2670fc4SToomas Soome dboot_multiboot2_next_tag(multiboot_tag_t *tag)
54*d2670fc4SToomas Soome {
55*d2670fc4SToomas Soome if (tag == NULL || tag->mb_type == MULTIBOOT_TAG_TYPE_END)
56*d2670fc4SToomas Soome return (NULL);
57*d2670fc4SToomas Soome
58*d2670fc4SToomas Soome return ((multiboot_tag_t *)P2ROUNDUP((uintptr_t)tag +
59*d2670fc4SToomas Soome tag->mb_size, MULTIBOOT_TAG_ALIGN));
60*d2670fc4SToomas Soome }
61*d2670fc4SToomas Soome
62*d2670fc4SToomas Soome /*
63*d2670fc4SToomas Soome * Walk the tag list until we hit the first instance of a given tag or
64*d2670fc4SToomas Soome * the end of the list.
65*d2670fc4SToomas Soome * MB2_NEXT_TAG() will return NULL on end of list.
66*d2670fc4SToomas Soome */
67*d2670fc4SToomas Soome static void *
dboot_multiboot2_find_tag_impl(multiboot_tag_t * tagp,uint32_t tag)68*d2670fc4SToomas Soome dboot_multiboot2_find_tag_impl(multiboot_tag_t *tagp, uint32_t tag)
69*d2670fc4SToomas Soome {
70*d2670fc4SToomas Soome while (tagp != NULL && tagp->mb_type != tag) {
71*d2670fc4SToomas Soome tagp = dboot_multiboot2_next_tag(tagp);
72*d2670fc4SToomas Soome }
73*d2670fc4SToomas Soome return (tagp);
74*d2670fc4SToomas Soome }
75*d2670fc4SToomas Soome
76*d2670fc4SToomas Soome /*
77*d2670fc4SToomas Soome * Walk the entire list to find the first instance of the given tag.
78*d2670fc4SToomas Soome */
79*d2670fc4SToomas Soome void *
dboot_multiboot2_find_tag(multiboot2_info_header_t * mbi,uint32_t tag)80*d2670fc4SToomas Soome dboot_multiboot2_find_tag(multiboot2_info_header_t *mbi, uint32_t tag)
81*d2670fc4SToomas Soome {
82*d2670fc4SToomas Soome multiboot_tag_t *tagp = dboot_multiboot2_first_tag(mbi);
83*d2670fc4SToomas Soome
84*d2670fc4SToomas Soome return (dboot_multiboot2_find_tag_impl(tagp, tag));
85*d2670fc4SToomas Soome }
86*d2670fc4SToomas Soome
87*d2670fc4SToomas Soome /*
88*d2670fc4SToomas Soome * dboot_multiboot2_iterate()
89*d2670fc4SToomas Soome *
90*d2670fc4SToomas Soome * While most tags in tag list are unique, the modules are specified
91*d2670fc4SToomas Soome * one module per tag and therefore we need an mechanism to process
92*d2670fc4SToomas Soome * tags in set.
93*d2670fc4SToomas Soome *
94*d2670fc4SToomas Soome * Arguments:
95*d2670fc4SToomas Soome * mbi: multiboot info header
96*d2670fc4SToomas Soome * data: callback context.
97*d2670fc4SToomas Soome *
98*d2670fc4SToomas Soome * Return value:
99*d2670fc4SToomas Soome * Processed item count.
100*d2670fc4SToomas Soome * Callback returning B_TRUE will terminate the iteration.
101*d2670fc4SToomas Soome */
102*d2670fc4SToomas Soome static int
dboot_multiboot2_iterate(multiboot2_info_header_t * mbi,struct dboot_multiboot2_iterate_ctx * ctx)103*d2670fc4SToomas Soome dboot_multiboot2_iterate(multiboot2_info_header_t *mbi,
104*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx *ctx)
105*d2670fc4SToomas Soome {
106*d2670fc4SToomas Soome dboot_multiboot2_iterate_cb_t callback = ctx->dboot_iter_callback;
107*d2670fc4SToomas Soome multiboot_tag_t *tagp;
108*d2670fc4SToomas Soome uint32_t tag = ctx->dboot_iter_tag;
109*d2670fc4SToomas Soome int index = 0;
110*d2670fc4SToomas Soome
111*d2670fc4SToomas Soome tagp = dboot_multiboot2_find_tag(mbi, tag);
112*d2670fc4SToomas Soome while (tagp != NULL) {
113*d2670fc4SToomas Soome if (callback != NULL) {
114*d2670fc4SToomas Soome if (callback(index, tagp, ctx) == B_TRUE) {
115*d2670fc4SToomas Soome return (index + 1);
116*d2670fc4SToomas Soome }
117*d2670fc4SToomas Soome }
118*d2670fc4SToomas Soome tagp = dboot_multiboot2_next_tag(tagp);
119*d2670fc4SToomas Soome tagp = dboot_multiboot2_find_tag_impl(tagp, tag);
120*d2670fc4SToomas Soome index++;
121*d2670fc4SToomas Soome }
122*d2670fc4SToomas Soome return (index);
123*d2670fc4SToomas Soome }
124*d2670fc4SToomas Soome
125*d2670fc4SToomas Soome char *
dboot_multiboot2_cmdline(multiboot2_info_header_t * mbi)126*d2670fc4SToomas Soome dboot_multiboot2_cmdline(multiboot2_info_header_t *mbi)
127*d2670fc4SToomas Soome {
128*d2670fc4SToomas Soome multiboot_tag_string_t *tag;
129*d2670fc4SToomas Soome
130*d2670fc4SToomas Soome tag = dboot_multiboot2_find_tag(mbi, MULTIBOOT_TAG_TYPE_CMDLINE);
131*d2670fc4SToomas Soome
132*d2670fc4SToomas Soome if (tag != NULL)
133*d2670fc4SToomas Soome return (&tag->mb_string[0]);
134*d2670fc4SToomas Soome else
135*d2670fc4SToomas Soome return (NULL);
136*d2670fc4SToomas Soome }
137*d2670fc4SToomas Soome
138*d2670fc4SToomas Soome /*
139*d2670fc4SToomas Soome * Simple callback to index item in set.
140*d2670fc4SToomas Soome * Terminates iteration if the indexed item is found.
141*d2670fc4SToomas Soome */
142*d2670fc4SToomas Soome static boolean_t
dboot_multiboot2_iterate_callback(int index,multiboot_tag_t * tagp,struct dboot_multiboot2_iterate_ctx * ctx)143*d2670fc4SToomas Soome dboot_multiboot2_iterate_callback(int index, multiboot_tag_t *tagp,
144*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx *ctx)
145*d2670fc4SToomas Soome {
146*d2670fc4SToomas Soome if (index == ctx->dboot_iter_index) {
147*d2670fc4SToomas Soome ctx->dboot_iter_tagp = tagp;
148*d2670fc4SToomas Soome return (B_TRUE);
149*d2670fc4SToomas Soome }
150*d2670fc4SToomas Soome return (B_FALSE);
151*d2670fc4SToomas Soome }
152*d2670fc4SToomas Soome
153*d2670fc4SToomas Soome int
dboot_multiboot2_modcount(multiboot2_info_header_t * mbi)154*d2670fc4SToomas Soome dboot_multiboot2_modcount(multiboot2_info_header_t *mbi)
155*d2670fc4SToomas Soome {
156*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx ctx = {
157*d2670fc4SToomas Soome .dboot_iter_callback = NULL,
158*d2670fc4SToomas Soome .dboot_iter_index = 0,
159*d2670fc4SToomas Soome .dboot_iter_tag = MULTIBOOT_TAG_TYPE_MODULE,
160*d2670fc4SToomas Soome .dboot_iter_tagp = NULL
161*d2670fc4SToomas Soome };
162*d2670fc4SToomas Soome
163*d2670fc4SToomas Soome return (dboot_multiboot2_iterate(mbi, &ctx));
164*d2670fc4SToomas Soome }
165*d2670fc4SToomas Soome
166*d2670fc4SToomas Soome uint32_t
dboot_multiboot2_modstart(multiboot2_info_header_t * mbi,int index)167*d2670fc4SToomas Soome dboot_multiboot2_modstart(multiboot2_info_header_t *mbi, int index)
168*d2670fc4SToomas Soome {
169*d2670fc4SToomas Soome multiboot_tag_module_t *tagp;
170*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx ctx = {
171*d2670fc4SToomas Soome .dboot_iter_callback = dboot_multiboot2_iterate_callback,
172*d2670fc4SToomas Soome .dboot_iter_index = index,
173*d2670fc4SToomas Soome .dboot_iter_tag = MULTIBOOT_TAG_TYPE_MODULE,
174*d2670fc4SToomas Soome .dboot_iter_tagp = NULL
175*d2670fc4SToomas Soome };
176*d2670fc4SToomas Soome
177*d2670fc4SToomas Soome if (dboot_multiboot2_iterate(mbi, &ctx) != 0) {
178*d2670fc4SToomas Soome tagp = (multiboot_tag_module_t *)ctx.dboot_iter_tagp;
179*d2670fc4SToomas Soome
180*d2670fc4SToomas Soome if (tagp != NULL)
181*d2670fc4SToomas Soome return (tagp->mb_mod_start);
182*d2670fc4SToomas Soome }
183*d2670fc4SToomas Soome return (0);
184*d2670fc4SToomas Soome }
185*d2670fc4SToomas Soome
186*d2670fc4SToomas Soome uint32_t
dboot_multiboot2_modend(multiboot2_info_header_t * mbi,int index)187*d2670fc4SToomas Soome dboot_multiboot2_modend(multiboot2_info_header_t *mbi, int index)
188*d2670fc4SToomas Soome {
189*d2670fc4SToomas Soome multiboot_tag_module_t *tagp;
190*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx ctx = {
191*d2670fc4SToomas Soome .dboot_iter_callback = dboot_multiboot2_iterate_callback,
192*d2670fc4SToomas Soome .dboot_iter_index = index,
193*d2670fc4SToomas Soome .dboot_iter_tag = MULTIBOOT_TAG_TYPE_MODULE,
194*d2670fc4SToomas Soome .dboot_iter_tagp = NULL
195*d2670fc4SToomas Soome };
196*d2670fc4SToomas Soome
197*d2670fc4SToomas Soome if (dboot_multiboot2_iterate(mbi, &ctx) != 0) {
198*d2670fc4SToomas Soome tagp = (multiboot_tag_module_t *)ctx.dboot_iter_tagp;
199*d2670fc4SToomas Soome
200*d2670fc4SToomas Soome if (tagp != NULL)
201*d2670fc4SToomas Soome return (tagp->mb_mod_end);
202*d2670fc4SToomas Soome }
203*d2670fc4SToomas Soome return (0);
204*d2670fc4SToomas Soome }
205*d2670fc4SToomas Soome
206*d2670fc4SToomas Soome char *
dboot_multiboot2_modcmdline(multiboot2_info_header_t * mbi,int index)207*d2670fc4SToomas Soome dboot_multiboot2_modcmdline(multiboot2_info_header_t *mbi, int index)
208*d2670fc4SToomas Soome {
209*d2670fc4SToomas Soome multiboot_tag_module_t *tagp;
210*d2670fc4SToomas Soome struct dboot_multiboot2_iterate_ctx ctx = {
211*d2670fc4SToomas Soome .dboot_iter_callback = dboot_multiboot2_iterate_callback,
212*d2670fc4SToomas Soome .dboot_iter_index = index,
213*d2670fc4SToomas Soome .dboot_iter_tag = MULTIBOOT_TAG_TYPE_MODULE,
214*d2670fc4SToomas Soome .dboot_iter_tagp = NULL
215*d2670fc4SToomas Soome };
216*d2670fc4SToomas Soome
217*d2670fc4SToomas Soome if (dboot_multiboot2_iterate(mbi, &ctx) != 0) {
218*d2670fc4SToomas Soome tagp = (multiboot_tag_module_t *)ctx.dboot_iter_tagp;
219*d2670fc4SToomas Soome
220*d2670fc4SToomas Soome if (tagp != NULL)
221*d2670fc4SToomas Soome return (&tagp->mb_cmdline[0]);
222*d2670fc4SToomas Soome }
223*d2670fc4SToomas Soome return (NULL);
224*d2670fc4SToomas Soome }
225*d2670fc4SToomas Soome
226*d2670fc4SToomas Soome multiboot_tag_mmap_t *
dboot_multiboot2_get_mmap_tagp(multiboot2_info_header_t * mbi)227*d2670fc4SToomas Soome dboot_multiboot2_get_mmap_tagp(multiboot2_info_header_t *mbi)
228*d2670fc4SToomas Soome {
229*d2670fc4SToomas Soome return (dboot_multiboot2_find_tag(mbi, MULTIBOOT_TAG_TYPE_MMAP));
230*d2670fc4SToomas Soome }
231*d2670fc4SToomas Soome
232*d2670fc4SToomas Soome boolean_t
dboot_multiboot2_basicmeminfo(multiboot2_info_header_t * mbi,uint32_t * lower,uint32_t * upper)233*d2670fc4SToomas Soome dboot_multiboot2_basicmeminfo(multiboot2_info_header_t *mbi,
234*d2670fc4SToomas Soome uint32_t *lower, uint32_t *upper)
235*d2670fc4SToomas Soome {
236*d2670fc4SToomas Soome multiboot_tag_basic_meminfo_t *mip;
237*d2670fc4SToomas Soome
238*d2670fc4SToomas Soome mip = dboot_multiboot2_find_tag(mbi, MULTIBOOT_TAG_TYPE_BASIC_MEMINFO);
239*d2670fc4SToomas Soome if (mip != NULL) {
240*d2670fc4SToomas Soome *lower = mip->mb_mem_lower;
241*d2670fc4SToomas Soome *upper = mip->mb_mem_upper;
242*d2670fc4SToomas Soome return (B_TRUE);
243*d2670fc4SToomas Soome }
244*d2670fc4SToomas Soome return (B_FALSE);
245*d2670fc4SToomas Soome }
246*d2670fc4SToomas Soome
247*d2670fc4SToomas Soome /*
248*d2670fc4SToomas Soome * Return the type of mmap entry referenced by index.
249*d2670fc4SToomas Soome */
250*d2670fc4SToomas Soome uint32_t
dboot_multiboot2_mmap_get_type(multiboot2_info_header_t * mbi,multiboot_tag_mmap_t * mb2_mmap_tagp,int index)251*d2670fc4SToomas Soome dboot_multiboot2_mmap_get_type(multiboot2_info_header_t *mbi,
252*d2670fc4SToomas Soome multiboot_tag_mmap_t *mb2_mmap_tagp, int index)
253*d2670fc4SToomas Soome {
254*d2670fc4SToomas Soome multiboot_mmap_entry_t *mapentp;
255*d2670fc4SToomas Soome
256*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
257*d2670fc4SToomas Soome mb2_mmap_tagp = dboot_multiboot2_get_mmap_tagp(mbi);
258*d2670fc4SToomas Soome
259*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
260*d2670fc4SToomas Soome return (0);
261*d2670fc4SToomas Soome
262*d2670fc4SToomas Soome if (dboot_multiboot2_mmap_nentries(mbi, mb2_mmap_tagp) < index)
263*d2670fc4SToomas Soome return (0);
264*d2670fc4SToomas Soome
265*d2670fc4SToomas Soome mapentp = (multiboot_mmap_entry_t *)(mb2_mmap_tagp->mb_entries +
266*d2670fc4SToomas Soome index * mb2_mmap_tagp->mb_entry_size);
267*d2670fc4SToomas Soome return (mapentp->mmap_type);
268*d2670fc4SToomas Soome }
269*d2670fc4SToomas Soome
270*d2670fc4SToomas Soome /*
271*d2670fc4SToomas Soome * Return the length of mmap entry referenced by index.
272*d2670fc4SToomas Soome */
273*d2670fc4SToomas Soome uint64_t
dboot_multiboot2_mmap_get_length(multiboot2_info_header_t * mbi,multiboot_tag_mmap_t * mb2_mmap_tagp,int index)274*d2670fc4SToomas Soome dboot_multiboot2_mmap_get_length(multiboot2_info_header_t *mbi,
275*d2670fc4SToomas Soome multiboot_tag_mmap_t *mb2_mmap_tagp, int index)
276*d2670fc4SToomas Soome {
277*d2670fc4SToomas Soome multiboot_mmap_entry_t *mapentp;
278*d2670fc4SToomas Soome
279*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
280*d2670fc4SToomas Soome mb2_mmap_tagp = dboot_multiboot2_get_mmap_tagp(mbi);
281*d2670fc4SToomas Soome
282*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
283*d2670fc4SToomas Soome return (0);
284*d2670fc4SToomas Soome
285*d2670fc4SToomas Soome if (dboot_multiboot2_mmap_nentries(mbi, mb2_mmap_tagp) < index)
286*d2670fc4SToomas Soome return (0);
287*d2670fc4SToomas Soome
288*d2670fc4SToomas Soome mapentp = (multiboot_mmap_entry_t *)(mb2_mmap_tagp->mb_entries +
289*d2670fc4SToomas Soome index * mb2_mmap_tagp->mb_entry_size);
290*d2670fc4SToomas Soome return (mapentp->mmap_len);
291*d2670fc4SToomas Soome }
292*d2670fc4SToomas Soome
293*d2670fc4SToomas Soome /*
294*d2670fc4SToomas Soome * Return the address from mmap entry referenced by index.
295*d2670fc4SToomas Soome */
296*d2670fc4SToomas Soome uint64_t
dboot_multiboot2_mmap_get_base(multiboot2_info_header_t * mbi,multiboot_tag_mmap_t * mb2_mmap_tagp,int index)297*d2670fc4SToomas Soome dboot_multiboot2_mmap_get_base(multiboot2_info_header_t *mbi,
298*d2670fc4SToomas Soome multiboot_tag_mmap_t *mb2_mmap_tagp, int index)
299*d2670fc4SToomas Soome {
300*d2670fc4SToomas Soome multiboot_mmap_entry_t *mapentp;
301*d2670fc4SToomas Soome
302*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
303*d2670fc4SToomas Soome mb2_mmap_tagp = dboot_multiboot2_get_mmap_tagp(mbi);
304*d2670fc4SToomas Soome
305*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
306*d2670fc4SToomas Soome return (0);
307*d2670fc4SToomas Soome
308*d2670fc4SToomas Soome if (dboot_multiboot2_mmap_nentries(mbi, mb2_mmap_tagp) < index)
309*d2670fc4SToomas Soome return (0);
310*d2670fc4SToomas Soome
311*d2670fc4SToomas Soome mapentp = (multiboot_mmap_entry_t *)(mb2_mmap_tagp->mb_entries +
312*d2670fc4SToomas Soome index * mb2_mmap_tagp->mb_entry_size);
313*d2670fc4SToomas Soome return (mapentp->mmap_addr);
314*d2670fc4SToomas Soome }
315*d2670fc4SToomas Soome
316*d2670fc4SToomas Soome /*
317*d2670fc4SToomas Soome * Count and return the number of mmap entries provided by the tag.
318*d2670fc4SToomas Soome */
319*d2670fc4SToomas Soome int
dboot_multiboot2_mmap_nentries(multiboot2_info_header_t * mbi,multiboot_tag_mmap_t * mb2_mmap_tagp)320*d2670fc4SToomas Soome dboot_multiboot2_mmap_nentries(multiboot2_info_header_t *mbi,
321*d2670fc4SToomas Soome multiboot_tag_mmap_t *mb2_mmap_tagp)
322*d2670fc4SToomas Soome {
323*d2670fc4SToomas Soome if (mb2_mmap_tagp == NULL)
324*d2670fc4SToomas Soome mb2_mmap_tagp = dboot_multiboot2_get_mmap_tagp(mbi);
325*d2670fc4SToomas Soome
326*d2670fc4SToomas Soome if (mb2_mmap_tagp != NULL) {
327*d2670fc4SToomas Soome return ((mb2_mmap_tagp->mb_size -
328*d2670fc4SToomas Soome offsetof(multiboot_tag_mmap_t, mb_entries)) /
329*d2670fc4SToomas Soome mb2_mmap_tagp->mb_entry_size);
330*d2670fc4SToomas Soome }
331*d2670fc4SToomas Soome return (0);
332*d2670fc4SToomas Soome }
333*d2670fc4SToomas Soome
334*d2670fc4SToomas Soome /*
335*d2670fc4SToomas Soome * Return the highest address used by info header.
336*d2670fc4SToomas Soome */
337*d2670fc4SToomas Soome paddr_t
dboot_multiboot2_highest_addr(multiboot2_info_header_t * mbi)338*d2670fc4SToomas Soome dboot_multiboot2_highest_addr(multiboot2_info_header_t *mbi)
339*d2670fc4SToomas Soome {
340*d2670fc4SToomas Soome return ((paddr_t)(uintptr_t)mbi + mbi->mbi_total_size);
341*d2670fc4SToomas Soome }
342