network boot: support loading complete ISOs via HTTP
Now I don't have to unpack (or loop mount) ISO to boot via HTTP. Also I can boot directly from any ALT mirror, like this: automatic=method:http,network:dhcp,server:mirror.yandex.ru,directory=/altlinux/images/p9/simply/aarch64/slinux-live-9.1.1-aarch64.iso Closes: #40710
This commit is contained in:
parent
736c89620f
commit
36b688d17a
@ -23,6 +23,7 @@
|
|||||||
#define IMAGE_LOCATION "/image"
|
#define IMAGE_LOCATION "/image"
|
||||||
#define STAGE2_LOCATION "/root"
|
#define STAGE2_LOCATION "/root"
|
||||||
#define LIVE_DEVICE "/dev/loop0"
|
#define LIVE_DEVICE "/dev/loop0"
|
||||||
|
#define LOMOUNT_DEVICE "/dev/loop3"
|
||||||
#define STAGE2FS "squashfs"
|
#define STAGE2FS "squashfs"
|
||||||
#define LIVEFS "squashfs"
|
#define LIVEFS "squashfs"
|
||||||
#ifndef STAGE2_BINNAME
|
#ifndef STAGE2_BINNAME
|
||||||
|
@ -133,7 +133,7 @@ set_loop (const char *device, const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * loopdev = "/dev/loop3"; /* Ugly. But do I care? */
|
char * loopdev = LOMOUNT_DEVICE; /* Ugly. But do I care? */
|
||||||
|
|
||||||
void del_loop(char *device)
|
void del_loop(char *device)
|
||||||
{
|
{
|
||||||
|
11
network.c
11
network.c
@ -998,6 +998,7 @@ enum return_type http_prepare(void)
|
|||||||
char *tmp;
|
char *tmp;
|
||||||
int fd;
|
int fd;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
int is_iso = 0;
|
||||||
|
|
||||||
snprintf(location_full, sizeof(location_full),
|
snprintf(location_full, sizeof(location_full),
|
||||||
"Please enter the name or IP address of the HTTP server, "
|
"Please enter the name or IP address of the HTTP server, "
|
||||||
@ -1009,6 +1010,13 @@ enum return_type http_prepare(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strcpy(location_full, answers[1]);
|
strcpy(location_full, answers[1]);
|
||||||
|
log_message("HTTP: trying to retrieve %s", location_full);
|
||||||
|
fd = http_download_file(answers[0], location_full, &size);
|
||||||
|
if (fd >= 0) {
|
||||||
|
is_iso = 1;
|
||||||
|
goto download;
|
||||||
|
}
|
||||||
|
|
||||||
tmp = get_ramdisk_realname();
|
tmp = get_ramdisk_realname();
|
||||||
strcat(location_full, tmp);
|
strcat(location_full, tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
@ -1026,6 +1034,7 @@ enum return_type http_prepare(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
download:
|
||||||
if (!ramdisk_possible(size)) {
|
if (!ramdisk_possible(size)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
stg1_error_message("HTTP install needs more than %u Mbytes of memory (detected %u Mbytes).",
|
stg1_error_message("HTTP install needs more than %u Mbytes of memory (detected %u Mbytes).",
|
||||||
@ -1035,7 +1044,7 @@ enum return_type http_prepare(void)
|
|||||||
|
|
||||||
log_message("HTTP: size of download %lu bytes", size);
|
log_message("HTTP: size of download %lu bytes", size);
|
||||||
|
|
||||||
results = load_ramdisk_fd(fd, size);
|
results = load_ramdisk_or_iso(fd, size, is_iso);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (results != RETURN_OK)
|
if (results != RETURN_OK)
|
||||||
return RETURN_ERROR;
|
return RETURN_ERROR;
|
||||||
|
70
tools.c
70
tools.c
@ -45,6 +45,7 @@
|
|||||||
#include "automatic.h"
|
#include "automatic.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/loop.h>
|
#include <linux/loop.h>
|
||||||
|
#include "lomount.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
@ -297,6 +298,45 @@ static void save_stuff_for_rescue(void)
|
|||||||
log_message("saved file %s for rescue (%d bytes)", file, i);
|
log_message("saved file %s for rescue (%d bytes)", file, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop mount ISO loaded to RAM, and open stage2
|
||||||
|
*
|
||||||
|
* @param ram_fd file descriptor of ISO image
|
||||||
|
* @return file descriptor of stage2 or -1 on error
|
||||||
|
*/
|
||||||
|
static int open_stage2_from_iso(int iso_fd)
|
||||||
|
{
|
||||||
|
int stage2_fd = -1;
|
||||||
|
const char *stage2 = get_ramdisk_path(IMAGE_LOCATION); /* /image/live */
|
||||||
|
if (!stage2) {
|
||||||
|
log_message("%s: get_ramdisk_size: got NULL", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (do_losetup_fd(LOMOUNT_DEVICE, iso_fd, NULL) < 0) {
|
||||||
|
log_message("%s: could not setup loopback for iso_fd", __func__);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
if (my_mount(LOMOUNT_DEVICE, IMAGE_LOCATION, "iso9660", 0)) {
|
||||||
|
log_message("%s: failed to mount ISO loopback", __func__);
|
||||||
|
goto out_del_loop;
|
||||||
|
}
|
||||||
|
stage2_fd = open(stage2, O_RDONLY);
|
||||||
|
if (stage2_fd < 0) {
|
||||||
|
log_message("%s: failed to open %s", __func__, stage2);
|
||||||
|
goto out_umount;
|
||||||
|
}
|
||||||
|
free((char *)stage2);
|
||||||
|
return stage2_fd;
|
||||||
|
|
||||||
|
out_umount:
|
||||||
|
umount(IMAGE_LOCATION);
|
||||||
|
out_del_loop:
|
||||||
|
del_loop(LOMOUNT_DEVICE);
|
||||||
|
out_free:
|
||||||
|
free((char *)stage2);
|
||||||
|
out:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief copy exactly len bytes from buffer to file descriptor
|
* @brief copy exactly len bytes from buffer to file descriptor
|
||||||
@ -382,7 +422,7 @@ out:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum return_type load_ramdisk_fd(int source_fd, unsigned long size)
|
enum return_type load_ramdisk_or_iso(int source_fd, unsigned long size, int is_iso)
|
||||||
{
|
{
|
||||||
int ram_fd;
|
int ram_fd;
|
||||||
char * wait_msg = "Loading program into memory...";
|
char * wait_msg = "Loading program into memory...";
|
||||||
@ -405,8 +445,26 @@ enum return_type load_ramdisk_fd(int source_fd, unsigned long size)
|
|||||||
}
|
}
|
||||||
end_progression();
|
end_progression();
|
||||||
|
|
||||||
|
if (is_iso) {
|
||||||
|
int stage2_fd = open_stage2_from_iso(ram_fd);
|
||||||
|
if (stage2_fd < 0) {
|
||||||
|
close(ram_fd);
|
||||||
|
stg1_error_message("Could not open stage2 from ISO in RAM");
|
||||||
|
return RETURN_ERROR;
|
||||||
|
}
|
||||||
|
/* got a (mounted) loopback device backed by ram_fd,
|
||||||
|
* ram_fd itself is not necessary any more */
|
||||||
|
close(ram_fd);
|
||||||
|
/* to setup loopback device from stage2_fd */
|
||||||
|
ram_fd = stage2_fd;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_losetup_fd(LIVE_DEVICE, ram_fd, NULL) < 0) {
|
if (do_losetup_fd(LIVE_DEVICE, ram_fd, NULL) < 0) {
|
||||||
close(ram_fd);
|
close(ram_fd);
|
||||||
|
if (is_iso) {
|
||||||
|
umount(IMAGE_LOCATION);
|
||||||
|
del_loop(LOMOUNT_DEVICE);
|
||||||
|
}
|
||||||
stg1_error_message("Could not setup loopback for 2nd stage");
|
stg1_error_message("Could not setup loopback for 2nd stage");
|
||||||
return RETURN_ERROR;
|
return RETURN_ERROR;
|
||||||
}
|
}
|
||||||
@ -416,6 +474,10 @@ enum return_type load_ramdisk_fd(int source_fd, unsigned long size)
|
|||||||
|
|
||||||
if (my_mount(LIVE_DEVICE, STAGE2_LOCATION, STAGE2FS, 0)) {
|
if (my_mount(LIVE_DEVICE, STAGE2_LOCATION, STAGE2FS, 0)) {
|
||||||
stg1_error_message("Failed to mount stage2");
|
stg1_error_message("Failed to mount stage2");
|
||||||
|
if (is_iso) {
|
||||||
|
umount(IMAGE_LOCATION);
|
||||||
|
del_loop(LOMOUNT_DEVICE);
|
||||||
|
}
|
||||||
return RETURN_ERROR;
|
return RETURN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,12 +489,18 @@ enum return_type load_ramdisk_fd(int source_fd, unsigned long size)
|
|||||||
log_message("rescue: failed to umount " STAGE2_LOCATION);
|
log_message("rescue: failed to umount " STAGE2_LOCATION);
|
||||||
return RETURN_ERROR;
|
return RETURN_ERROR;
|
||||||
}
|
}
|
||||||
|
if (is_iso) {
|
||||||
|
/* XXX: should I do anything special here? */
|
||||||
|
}
|
||||||
return RETURN_OK; /* fucksike, I lost several hours wondering why the kernel won't see the rescue if it is alreay mounted */
|
return RETURN_OK; /* fucksike, I lost several hours wondering why the kernel won't see the rescue if it is alreay mounted */
|
||||||
}
|
}
|
||||||
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum return_type load_ramdisk_fd(int source_fd, unsigned long size) {
|
||||||
|
return load_ramdisk_or_iso(source_fd, size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int splash_verbose()
|
int splash_verbose()
|
||||||
{
|
{
|
||||||
|
1
tools.h
1
tools.h
@ -36,6 +36,7 @@ int ramdisk_possible(unsigned long ramdisk_size);
|
|||||||
char * get_ramdisk_realname(void);
|
char * get_ramdisk_realname(void);
|
||||||
enum return_type load_ramdisk(char *, unsigned long size);
|
enum return_type load_ramdisk(char *, unsigned long size);
|
||||||
enum return_type load_ramdisk_fd(int ramdisk_fd, unsigned long size);
|
enum return_type load_ramdisk_fd(int ramdisk_fd, unsigned long size);
|
||||||
|
enum return_type load_ramdisk_or_iso(int ramdisk_fd, unsigned long size, int is_iso);
|
||||||
void * memdup(void *src, size_t size);
|
void * memdup(void *src, size_t size);
|
||||||
void add_to_env(char * name, char * value);
|
void add_to_env(char * name, char * value);
|
||||||
void handle_env(char ** env);
|
void handle_env(char ** env);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user