1 #include <grub/types.h>
3 #include <grub/linux.h>
28 struct grub_linux_initrd_component
43 hex (grub_uint8_t val
)
47 return 'a' + val
- 10;
51 set_field (char *var
, grub_uint32_t val
)
55 for (i
= 28; i
>= 0; i
-= 4)
56 *ptr
++ = hex((val
>> i
) & 0xf);
60 make_header (grub_uint8_t
*ptr
,
61 const char *name
, grub_size_t len
,
65 struct newc_head
*head
= (struct newc_head
*) ptr
;
68 grub_memcpy (head
->magic
, "070701", 6);
69 set_field (head
->ino
, 0);
70 set_field (head
->mode
, mode
);
71 set_field (head
->uid
, 0);
72 set_field (head
->gid
, 0);
73 set_field (head
->nlink
, 1);
74 set_field (head
->mtime
, 0);
75 set_field (head
->filesize
, fsize
);
76 set_field (head
->devmajor
, 0);
77 set_field (head
->devminor
, 0);
78 set_field (head
->rdevmajor
, 0);
79 set_field (head
->rdevminor
, 0);
80 set_field (head
->namesize
, len
);
81 set_field (head
->check
, 0);
83 ptr
+= sizeof (struct newc_head
);
84 grub_memcpy (ptr
, name
, len
);
86 oh
= ALIGN_UP_OVERHEAD (ptr
- optr
, 4);
87 grub_memset (ptr
, 0, oh
);
93 free_dir (struct dir
*root
)
97 free_dir (root
->next
);
98 free_dir (root
->child
);
99 grub_free (root
->name
);
104 insert_dir (const char *name
, struct dir
**root
,
107 struct dir
*cur
, **head
= root
;
108 const char *cb
, *ce
= name
;
109 grub_size_t size
= 0;
112 for (cb
= ce
; *cb
== '/'; cb
++);
113 for (ce
= cb
; *ce
&& *ce
!= '/'; ce
++);
117 for (cur
= *root
; cur
; cur
= cur
->next
)
118 if (grub_memcmp (cur
->name
, cb
, ce
- cb
)
119 && cur
->name
[ce
- cb
] == 0)
124 n
= grub_zalloc (sizeof (*n
));
128 n
->name
= grub_strndup (cb
, ce
- cb
);
132 * Create the substring with the trailing NUL byte
133 * to be included in the cpio header.
135 char *tmp_name
= grub_strndup (name
, ce
- name
);
141 grub_dprintf ("linux", "Creating directory %s, %s\n", name
, ce
);
142 ptr
= make_header (ptr
, tmp_name
, ce
- name
+ 1,
144 grub_free (tmp_name
);
146 size
+= ALIGN_UP ((ce
- (char *) name
+ 1)
147 + sizeof (struct newc_head
), 4);
157 grub_initrd_init (int argc
, char *argv
[],
158 struct grub_linux_initrd_context
*initrd_ctx
)
162 struct dir
*root
= 0;
164 initrd_ctx
->nfiles
= 0;
165 initrd_ctx
->components
= 0;
167 initrd_ctx
->components
= grub_zalloc (argc
168 * sizeof (initrd_ctx
->components
[0]));
169 if (!initrd_ctx
->components
)
172 initrd_ctx
->size
= 0;
174 for (i
= 0; i
< argc
; i
++)
176 const char *fname
= argv
[i
];
178 initrd_ctx
->size
= ALIGN_UP (initrd_ctx
->size
, 4);
180 if (grub_memcmp (argv
[i
], "newc:", 5) == 0)
182 const char *ptr
, *eptr
;
186 eptr
= grub_strchr (ptr
, ':');
189 initrd_ctx
->components
[i
].newc_name
= grub_strndup (ptr
, eptr
- ptr
);
190 if (!initrd_ctx
->components
[i
].newc_name
)
192 grub_initrd_close (initrd_ctx
);
196 += ALIGN_UP (sizeof (struct newc_head
)
197 + grub_strlen (initrd_ctx
->components
[i
].newc_name
) + 1,
199 initrd_ctx
->size
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
207 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
208 + sizeof ("TRAILER!!!"), 4);
213 initrd_ctx
->components
[i
].file
= grub_file_open (fname
,
214 GRUB_FILE_TYPE_LINUX_INITRD
215 | GRUB_FILE_TYPE_NO_DECOMPRESS
);
216 if (!initrd_ctx
->components
[i
].file
)
218 grub_initrd_close (initrd_ctx
);
221 initrd_ctx
->nfiles
++;
222 initrd_ctx
->components
[i
].size
223 = grub_file_size (initrd_ctx
->components
[i
].file
);
224 initrd_ctx
->size
+= initrd_ctx
->components
[i
].size
;
229 initrd_ctx
->size
= ALIGN_UP (initrd_ctx
->size
, 4);
230 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
231 + sizeof ("TRAILER!!!"), 4);
236 return GRUB_ERR_NONE
;
240 grub_get_initrd_size (struct grub_linux_initrd_context
*initrd_ctx
)
242 return initrd_ctx
->size
;
246 grub_initrd_close (struct grub_linux_initrd_context
*initrd_ctx
)
249 if (!initrd_ctx
->components
)
251 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
253 grub_free (initrd_ctx
->components
[i
].newc_name
);
254 grub_file_close (initrd_ctx
->components
[i
].file
);
256 grub_free (initrd_ctx
->components
);
257 initrd_ctx
->components
= 0;
260 extern int ventoy_need_prompt_load_file(void);
261 extern grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
);
263 grub_initrd_load (struct grub_linux_initrd_context
*initrd_ctx
,
264 char *argv
[], void *target
)
266 grub_uint8_t
*ptr
= target
;
269 struct dir
*root
= 0;
270 grub_ssize_t cursize
= 0;
271 grub_ssize_t readsize
= 0;
273 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
275 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
276 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
278 if (initrd_ctx
->components
[i
].newc_name
)
280 ptr
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
282 ptr
= make_header (ptr
, initrd_ctx
->components
[i
].newc_name
,
283 grub_strlen (initrd_ctx
->components
[i
].newc_name
) + 1,
285 initrd_ctx
->components
[i
].size
);
290 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!"),
297 cursize
= initrd_ctx
->components
[i
].size
;
298 if (ventoy_need_prompt_load_file() && initrd_ctx
->components
[i
].newc_name
&&
299 grub_strcmp(initrd_ctx
->components
[i
].newc_name
, "boot.wim") == 0)
301 readsize
= ventoy_load_file_with_prompt(initrd_ctx
->components
[i
].file
, ptr
, cursize
);
305 readsize
= grub_file_read (initrd_ctx
->components
[i
].file
, ptr
, cursize
);
308 if (readsize
!= cursize
)
311 grub_error (GRUB_ERR_FILE_READ_ERROR
, N_("premature end of file %s"),
313 grub_initrd_close (initrd_ctx
);
320 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
321 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
322 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!"), 0, 0);
326 return GRUB_ERR_NONE
;