1 /*
2 * Copyright (c) 2021 - 2022, Intel Corporation.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Intel Corporation nor the names of its
15 * contributors may be used to endorse or promote products
16 * derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <efi.h>
34 #include <efilib.h>
35 #include "boot.h"
36 #include "stdlib.h"
37 #include "multiboot.h"
38
39 /**
40 * @brief Search the first len bytes in buffer for multiboot1 header.
41 *
42 * @param[in] buffer Buffer to be searched
43 * @param[in] len Search length
44 *
45 * @return A pointer to the multiboot1 header if found. NULL otherwise.
46 */
find_mb1header(const UINT8 * buffer,uint64_t len)47 const struct multiboot_header *find_mb1header(const UINT8 *buffer, uint64_t len)
48 {
49 const struct multiboot_header *header;
50
51 for (header = (struct multiboot_header *)buffer;
52 ((char *)header <= (char *)buffer + len - 12);
53 header = (struct multiboot_header *)((char *)header + MULTIBOOT_HEADER_ALIGN))
54 {
55 if (header->mh_magic == MULTIBOOT_HEADER_MAGIC &&
56 !(header->mh_magic + header->mh_flags + header->mh_checksum))
57 return header;
58 }
59
60 return NULL;
61 }
62
63 /**
64 * @brief Search the first len bytes in buffer for multiboot2 header.
65 *
66 * @param[in] buffer Buffer to be searched
67 * @param[in] len Search length
68 *
69 * @return A pointer to the multiboot2 header if found. NULL otherwise.
70 */
find_mb2header(const UINT8 * buffer,uint64_t len)71 const struct multiboot2_header *find_mb2header(const UINT8 *buffer, uint64_t len)
72 {
73 const struct multiboot2_header *header;
74
75 for (header = (const struct multiboot2_header *)buffer;
76 ((char *)header <= (char *)buffer + len - 12);
77 header = (struct multiboot2_header *)((uint64_t)header + MULTIBOOT2_HEADER_ALIGN / 4))
78 {
79 if (header->magic == MULTIBOOT2_HEADER_MAGIC &&
80 !(header->magic + header->architecture + header->header_length + header->checksum) &&
81 header->architecture == MULTIBOOT2_ARCHITECTURE_I386)
82 return header;
83 }
84
85 return NULL;
86 }
87
88 /**
89 * @brief Parse the multiboot2 header and return a list of pointers to the header tags.
90 *
91 * @param[in] header Multiboot2 header to be parsed.
92 * @param[out] hv_tags An hv_mb2header_tag_list struct that contains pointers to all possible
93 * tags in a multiboot2 header. If a field in this struct is not NULL, it
94 * means the tag was found in the given header. NULL otherwise.
95 *
96 * @return 0 on success. -1 on error.
97 */
parse_mb2header(const struct multiboot2_header * header,struct hv_mb2header_tag_list * hv_tags)98 int parse_mb2header(const struct multiboot2_header *header, struct hv_mb2header_tag_list *hv_tags)
99 {
100 struct multiboot2_header_tag *tag;
101
102 memset(hv_tags, 0, sizeof(struct hv_mb2header_tag_list));
103
104 for (tag = (struct multiboot2_header_tag *)(header + 1);
105 tag->type != MULTIBOOT2_TAG_TYPE_END;
106 tag = (struct multiboot2_header_tag *)((uint32_t *)tag + ALIGN_UP(tag->size, MULTIBOOT2_TAG_ALIGN) / 4))
107 {
108 switch (tag->type) {
109 case MULTIBOOT2_HEADER_TAG_INFORMATION_REQUEST:
110 /* Ignored. Currently we didn't support all categories of requested information,
111 * only the part that ACRN requests. So we don't parse the requests here. */
112 break;
113
114 case MULTIBOOT2_HEADER_TAG_ADDRESS:
115 hv_tags->addr = (struct multiboot2_header_tag_address *)tag;
116 break;
117
118 case MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS:
119 hv_tags->entry = (struct multiboot2_header_tag_entry_address *)tag;
120 break;
121
122 case MULTIBOOT2_HEADER_TAG_RELOCATABLE:
123 hv_tags->reloc = (struct multiboot2_header_tag_relocatable *)tag;
124 break;
125
126 default:
127 Print(L"Unsupported multiboot2 tag type: %d\n", tag->type);
128 return -1;
129 }
130 }
131
132 if (hv_tags->addr && !hv_tags->entry)
133 return -1;
134
135 return 0;
136 }
137