mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zipl: add basic support of environment block by zipl(8)
When installing a boot record for "ipl" and "menu" job, always add an environment block as a boot component located in bootmap file at offset alinged on file system block size boundary. When adding, first try to import environment from a file at location specified by newly introduced "--environment" zipl option, or by default at "/etc/ziplenv". If nothing was imported, then add a blank environment block. Optionally print the content of the environment block. Store environment block size and address (as of boot component) in stage3_parms. Change interface of add_ipl_program(): add 2 additional arguments: a pointer to bootmap file name and a predicate indicating if we need to add environment block as a boot component. Reviewed-by: Stefan Haberland <sth@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
bbeb0f8445
commit
1fb859729e
@@ -36,8 +36,10 @@ struct stage3_parms {
|
||||
unsigned long long flags; /* flags (e.g. STAGE3_FLAG_KDUMP) */
|
||||
unsigned long long image_len; /* length of kernel */
|
||||
unsigned long long image_addr; /* target address of kernel */
|
||||
unsigned long long envblk_addr; /* address of environment block */
|
||||
unsigned long long envblk_len; /* size of environment block */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct stage3_parms) == 8 * 8)
|
||||
STATIC_ASSERT(sizeof(struct stage3_parms) == 8 * 10)
|
||||
|
||||
extern struct stage3_parms _stage3_parms;
|
||||
extern void kdump_stage3();
|
||||
|
||||
@@ -296,7 +296,8 @@ int boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job);
|
||||
int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
||||
address_t initrd_addr, size_t initrd_len,
|
||||
address_t entry, int extra_parm, uint64_t flags,
|
||||
address_t image_addr, size_t image_len);
|
||||
address_t image_addr, size_t image_len,
|
||||
address_t envblk_addr, size_t envblk_len);
|
||||
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
|
||||
address_t initrd_addr, address_t image_addr);
|
||||
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
|
||||
|
||||
@@ -17,10 +17,20 @@
|
||||
#include "disk.h"
|
||||
#include "job.h"
|
||||
#include "zipl.h"
|
||||
#include "stddef.h"
|
||||
|
||||
#define BOOTMAP_HEADER_VERSION 1
|
||||
|
||||
#define SIGNATURE_MAGIC "~Module signature appended~\n"
|
||||
#define PKCS7_FORMAT 0x01
|
||||
|
||||
struct bootmap_header {
|
||||
char header_text[48];
|
||||
u64 version;
|
||||
u64 envblk_offset;
|
||||
char reserved[448];
|
||||
};
|
||||
|
||||
struct signature_header {
|
||||
uint8_t format;
|
||||
uint8_t reserved[3];
|
||||
@@ -50,6 +60,9 @@ struct file_signature {
|
||||
|
||||
#define PKEY_ID_PKCS7 0x02
|
||||
|
||||
int bootmap_header_init(int fd);
|
||||
int bootmap_header_read(int fd, struct bootmap_header *bh);
|
||||
int bootmap_header_write(int fd, struct bootmap_header *bh);
|
||||
int bootmap_create(struct job_data* job, disk_blockptr_t* program_table,
|
||||
disk_blockptr_t *scsi_dump_sb_blockptr,
|
||||
disk_blockptr_t** stage2_list, blocknum_t* stage2_count,
|
||||
|
||||
34
zipl/include/envblk.h
Normal file
34
zipl/include/envblk.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* s390-tools/zipl/include/bootmap.h
|
||||
* Functions to handle environment block.
|
||||
*
|
||||
* Copyright IBM Corp. 2020
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*
|
||||
*/
|
||||
#include "boot/s390.h" /* for PAGE_SIZE */
|
||||
|
||||
#define ZIPL_ENVBLK_SIGNATURE "# zIPL Environment Block\n"
|
||||
#define ENVBLK_DEFAULT_IMPORT_SOURCE "/etc/ziplenv"
|
||||
/*
|
||||
* The following limit can be increased. It requires modifications
|
||||
* of the code, which is responsible for handling environment in
|
||||
* stage3, which will increase its memory footprint.
|
||||
*/
|
||||
#define ENVBLK_MAX_LINES (PAGE_SIZE / 8 /* sizeof(struct env_hash_entry */)
|
||||
|
||||
#define ENVBLK_MAX_IMPORT_SIZE(envblk_size) \
|
||||
(envblk_size - sizeof(ZIPL_ENVBLK_SIGNATURE) + 1)
|
||||
|
||||
int envblk_offset_get(int fd, off_t *off);
|
||||
int envblk_offset_set(int fd, off_t off);
|
||||
int envblk_size_get(int fd, int *size);
|
||||
int envblk_check_name(char *name, int len);
|
||||
int envblk_import(char *from, char *to, int size);
|
||||
char *envblk_next_line(char *s, const char *end);
|
||||
int envblk_scan(char *envblk, unsigned int envblk_size,
|
||||
void (*actor)(char *name));
|
||||
void envblk_print(char *envblk, unsigned int envblk_size);
|
||||
void envblk_create_blank(char *envblk, int envblk_len);
|
||||
@@ -46,9 +46,15 @@ struct job_ipl_data {
|
||||
address_t image_addr;
|
||||
address_t parm_addr;
|
||||
address_t ramdisk_addr;
|
||||
address_t envblk_addr;
|
||||
int is_kdump;
|
||||
};
|
||||
|
||||
struct job_envblk_data {
|
||||
int size;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
struct job_segment_data {
|
||||
char* segment;
|
||||
address_t segment_addr;
|
||||
@@ -108,6 +114,7 @@ struct job_menu_data {
|
||||
struct job_data {
|
||||
enum job_id id;
|
||||
struct job_target_data target;
|
||||
struct job_envblk_data envblk;
|
||||
char* name;
|
||||
union {
|
||||
struct job_ipl_data ipl;
|
||||
|
||||
@@ -138,6 +138,11 @@ the target directory. Supported devices are DASD and SCSI disks.
|
||||
It is not possible to specify both this parameter and the name of a menu
|
||||
or configuration section on the command line at the same time.
|
||||
|
||||
.TP
|
||||
.BR "\-\-environment=<FILE>"
|
||||
Import zIPL environment from specified <FILE>. If none is supplied,
|
||||
it will be imported from "/etc/ziplenv".
|
||||
|
||||
.TP
|
||||
.BR "\-\-targetbase=<BASE DEVICE>"
|
||||
Install the actual boot loader on the device node specified by BASE DEVICE.
|
||||
|
||||
@@ -10,7 +10,7 @@ ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS)
|
||||
libs = $(rootdir)/libutil/libutil.a
|
||||
|
||||
objects = misc.o error.o scan.o job.o boot.o bootmap.o disk.o \
|
||||
install.o zipl.o $(rootdir)/zipl/boot/data.o
|
||||
bootmap_header.o envblk.o install.o zipl.o $(rootdir)/zipl/boot/data.o
|
||||
|
||||
zipl_helpers = $(basename $(wildcard zipl_helper.*.c))
|
||||
chreipl_helpers = $(subst zipl_,chreipl_, $(zipl_helpers))
|
||||
|
||||
@@ -82,7 +82,8 @@ int
|
||||
boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
||||
address_t initrd_addr, size_t initrd_len,
|
||||
address_t entry, int extra_parm, uint64_t flags,
|
||||
address_t image_addr, size_t image_len)
|
||||
address_t image_addr, size_t image_len,
|
||||
address_t envblk_addr, size_t envblk_len)
|
||||
{
|
||||
struct stage3_parms params;
|
||||
void* data;
|
||||
@@ -106,6 +107,8 @@ boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
||||
params.flags = flags;
|
||||
params.image_len = (uint64_t) image_len;
|
||||
params.image_addr = (uint64_t) image_addr;
|
||||
params.envblk_addr = (uint64_t) envblk_addr;
|
||||
params.envblk_len = (uint64_t) envblk_len;
|
||||
/* Initialize buffer */
|
||||
memcpy(data, ¶ms, sizeof(params));
|
||||
*buffer = data;
|
||||
|
||||
@@ -27,19 +27,15 @@
|
||||
|
||||
#include "boot.h"
|
||||
#include "bootmap.h"
|
||||
#include "envblk.h"
|
||||
#include "disk.h"
|
||||
#include "error.h"
|
||||
#include "install.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Header text of the bootmap file */
|
||||
static const char header_text[] = "zSeries bootmap file\n"
|
||||
"created by zIPL\n";
|
||||
|
||||
/* Pointer to dedicated empty block in bootmap. */
|
||||
disk_blockptr_t empty_block;
|
||||
|
||||
|
||||
/* Get size of a bootmap block pointer for disk with given INFO. */
|
||||
static int
|
||||
get_blockptr_size(struct disk_info* info)
|
||||
@@ -522,8 +518,9 @@ check_remaining_filesize(size_t filesize, size_t signature_size,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
static int add_ipl_program(int fd, char *filename,
|
||||
bool add_envblk, struct job_envblk_data *envblk,
|
||||
struct job_ipl_data *ipl, disk_blockptr_t *program,
|
||||
int verbose, int add_files, component_header_type type,
|
||||
struct disk_info* info, struct job_target_data* target,
|
||||
int is_secure)
|
||||
@@ -533,12 +530,13 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
size_t ramdisk_size, image_size;
|
||||
bool secure_boot_supported;
|
||||
size_t stage3_params_size;
|
||||
const char *comp_name[10];
|
||||
const char *comp_name[11];
|
||||
size_t signature_size;
|
||||
int offset;
|
||||
uint64_t flags = 0;
|
||||
void *stage3_params;
|
||||
struct stat stats;
|
||||
off_t envblk_off;
|
||||
void *signature;
|
||||
int comp_nr = 0;
|
||||
void *table;
|
||||
@@ -676,7 +674,8 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
ipl->is_kdump ? IMAGE_ENTRY_KDUMP :
|
||||
IMAGE_ENTRY,
|
||||
(info->type == disk_type_scsi) ? 0 : 1,
|
||||
flags, ipl->image_addr, image_size);
|
||||
flags, ipl->image_addr, image_size,
|
||||
ipl->envblk_addr, envblk->size);
|
||||
if (rc) {
|
||||
free(table);
|
||||
return rc;
|
||||
@@ -769,8 +768,7 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
comp_name[comp_nr] = "parmline";
|
||||
comp_nr++;
|
||||
}
|
||||
|
||||
/* finally add ramdisk */
|
||||
/* add ramdisk */
|
||||
if (ipl->ramdisk != NULL) {
|
||||
signature_size = extract_signature(ipl->ramdisk, &signature,
|
||||
&sig_head);
|
||||
@@ -815,6 +813,65 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
comp_name[comp_nr] = "initial ramdisk";
|
||||
comp_nr++;
|
||||
}
|
||||
if (add_envblk == true) {
|
||||
/*
|
||||
* finally add environment block
|
||||
*/
|
||||
rc = envblk_offset_get(fd, &envblk_off);
|
||||
if (rc) {
|
||||
free(table);
|
||||
return rc;
|
||||
}
|
||||
if (envblk_off == 0) {
|
||||
/*
|
||||
* write with fs_block_size alignment to make sure that the
|
||||
* logical environment block will get to single file system
|
||||
* block
|
||||
*/
|
||||
rc = add_component_buffer_align(fd,
|
||||
envblk->buf, envblk->size,
|
||||
(component_data)ipl->envblk_addr,
|
||||
VOID_ADD(table, offset),
|
||||
info, &comp_loc[comp_nr],
|
||||
component_load,
|
||||
info->fs_block_size,
|
||||
&envblk_off);
|
||||
if (rc) {
|
||||
error_text("Could not add environment block");
|
||||
free(table);
|
||||
return rc;
|
||||
}
|
||||
assert(envblk_off % info->fs_block_size == 0);
|
||||
/*
|
||||
* store environment block location
|
||||
* in the bootmap header
|
||||
*/
|
||||
rc = envblk_offset_set(fd, envblk_off);
|
||||
if (rc) {
|
||||
error_text("Could not store environment block location");
|
||||
free(table);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
struct file_range reg;
|
||||
|
||||
reg.offset = envblk_off;
|
||||
reg.len = envblk->size;
|
||||
rc = add_component_file_range(fd, filename, ®,
|
||||
ipl->envblk_addr, 0,
|
||||
VOID_ADD(table, offset),
|
||||
0, info, target,
|
||||
&comp_loc[comp_nr]);
|
||||
if (rc) {
|
||||
error_text("Could not add environment block");
|
||||
free(table);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
offset += sizeof(struct component_entry);
|
||||
comp_name[comp_nr] = "environment blk";
|
||||
comp_nr++;
|
||||
}
|
||||
if (verbose)
|
||||
print_components(comp_name, comp_loc, comp_nr);
|
||||
/* Terminate component table */
|
||||
@@ -962,7 +1019,7 @@ add_dump_program(int fd, struct job_dump_data* dump,
|
||||
if (rc)
|
||||
return rc;
|
||||
ipl.parm_addr = dump->parm_addr;
|
||||
return add_ipl_program(fd, &ipl, program, verbose, 1,
|
||||
return add_ipl_program(fd, NULL, false, NULL, &ipl, program, verbose, 1,
|
||||
type, info, target, SECURE_BOOT_DISABLED);
|
||||
}
|
||||
|
||||
@@ -970,8 +1027,8 @@ add_dump_program(int fd, struct job_dump_data* dump,
|
||||
/* Build a program table from job data and set pointer to program table
|
||||
* block upon success. */
|
||||
static int
|
||||
build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
|
||||
struct disk_info* info)
|
||||
build_program_table(int fd, char *filename, struct job_data *job,
|
||||
disk_blockptr_t *pointer, struct disk_info *info)
|
||||
{
|
||||
disk_blockptr_t* table;
|
||||
int entries, component_header;
|
||||
@@ -985,6 +1042,7 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
|
||||
entries);
|
||||
if (table == NULL)
|
||||
return -1;
|
||||
|
||||
memset((void *) table, 0, sizeof(disk_blockptr_t) * entries);
|
||||
/* Add programs */
|
||||
switch (job->id) {
|
||||
@@ -998,8 +1056,9 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
|
||||
component_header = component_header_dump;
|
||||
else
|
||||
component_header = component_header_ipl;
|
||||
rc = add_ipl_program(fd, &job->data.ipl, &table[0],
|
||||
verbose || job->command_line,
|
||||
rc = add_ipl_program(fd, filename,
|
||||
true, &job->envblk, &job->data.ipl,
|
||||
&table[0], verbose || job->command_line,
|
||||
job->add_files, component_header,
|
||||
info, &job->target, job->is_secure);
|
||||
break;
|
||||
@@ -1052,7 +1111,8 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
|
||||
else
|
||||
is_secure =
|
||||
job->data.menu.entry[i].is_secure;
|
||||
rc = add_ipl_program(fd,
|
||||
rc = add_ipl_program(fd, filename,
|
||||
true, &job->envblk,
|
||||
&job->data.menu.entry[i].data.ipl,
|
||||
&table[job->data.menu.entry[i].pos],
|
||||
verbose || job->command_line,
|
||||
@@ -1086,6 +1146,9 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
if (job->envblk.buf && verbose)
|
||||
envblk_print(job->envblk.buf, job->envblk.size);
|
||||
|
||||
if (rc == 0) {
|
||||
/* Add program table block */
|
||||
rc = add_program_table(fd, table, entries, pointer, info);
|
||||
@@ -1244,9 +1307,9 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
|
||||
scsi_sb.dump_size = unused_size;
|
||||
}
|
||||
|
||||
/* Write bootmap header */
|
||||
if (misc_write(fd, header_text, sizeof(header_text))) {
|
||||
error_text("Could not write to file '%s'", filename);
|
||||
/* Initialize bootmap header */
|
||||
if (bootmap_header_init(fd)) {
|
||||
error_text("Could not init bootmap header at '%s'", filename);
|
||||
goto out_misc_free_temp_dev;
|
||||
}
|
||||
/* Write empty block to be read in place of holes in files */
|
||||
@@ -1255,7 +1318,7 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
|
||||
goto out_misc_free_temp_dev;
|
||||
}
|
||||
/* Build program table */
|
||||
if (build_program_table(fd, job, program_table, info))
|
||||
if (build_program_table(fd, filename, job, program_table, info))
|
||||
goto out_misc_free_temp_dev;
|
||||
if (job->id == job_dump_partition) {
|
||||
scsi_sb.magic = SCSI_DUMP_SB_MAGIC;
|
||||
|
||||
64
zipl/src/bootmap_header.c
Normal file
64
zipl/src/bootmap_header.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* zipl - zSeries Initial Program Loader tool
|
||||
*
|
||||
* Functions to manipulate with bootmap header
|
||||
*
|
||||
* Copyright IBM Corp. 2021
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootmap.h"
|
||||
#include "error.h"
|
||||
#include "misc.h"
|
||||
|
||||
int bootmap_header_init(int fd)
|
||||
{
|
||||
struct bootmap_header bh = {
|
||||
.header_text =
|
||||
"zSeries bootmap file\n"
|
||||
"created by zIPL\n",
|
||||
.version = BOOTMAP_HEADER_VERSION
|
||||
};
|
||||
|
||||
return misc_write(fd, &bh, sizeof(bh));
|
||||
}
|
||||
|
||||
static int bootmap_header_access(int fd, struct bootmap_header *bh, int read)
|
||||
{
|
||||
off_t cur_off;
|
||||
int ret;
|
||||
|
||||
cur_off = lseek(fd, 0, SEEK_CUR);
|
||||
if (cur_off == -1) {
|
||||
error_reason(strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (lseek(fd, 0, SEEK_SET) == -1) {
|
||||
error_reason(strerror(errno));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (read)
|
||||
ret = misc_read(fd, bh, sizeof(*bh));
|
||||
else
|
||||
ret = misc_write(fd, bh, sizeof(*bh));
|
||||
out:
|
||||
if (lseek(fd, cur_off, SEEK_SET) == -1)
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bootmap_header_read(int fd, struct bootmap_header *bh)
|
||||
{
|
||||
return bootmap_header_access(fd, bh, 1);
|
||||
}
|
||||
|
||||
int bootmap_header_write(int fd, struct bootmap_header *bh)
|
||||
{
|
||||
return bootmap_header_access(fd, bh, 0);
|
||||
}
|
||||
@@ -23,9 +23,10 @@
|
||||
#include <unistd.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fiemap.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "lib/util_proc.h"
|
||||
#include "lib/util_sys.h"
|
||||
|
||||
#include "disk.h"
|
||||
#include "error.h"
|
||||
#include "install.h"
|
||||
@@ -1085,9 +1086,9 @@ disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count,
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of pointers to the disk blocks that make up the whole
|
||||
* file specified by FILENAME, or only its part specified by REG (if the
|
||||
* last one is not NULL).
|
||||
* Retrieve a list of pointers to the disk blocks that make up a continuous
|
||||
* region REG in a file specified by FILENAME. If REG is NULL, then retrieve
|
||||
* a list of pointers for the whole file.
|
||||
* Upon success, return the number of blocks and set BLOCKLIST to point to
|
||||
* the uncompacted list. INFO provides information about the device which
|
||||
* contains the file. Return zero otherwise
|
||||
@@ -1121,18 +1122,19 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg,
|
||||
return 0;
|
||||
}
|
||||
if (reg) {
|
||||
/*
|
||||
* case of not block-aligned offsets is not implemented
|
||||
*/
|
||||
assert(reg->offset % info->phy_block_size == 0);
|
||||
|
||||
off = reg->offset;
|
||||
count = reg->len;
|
||||
} else {
|
||||
off = 0;
|
||||
count = stats.st_size;
|
||||
}
|
||||
if (off >= stats.st_size) {
|
||||
error_reason("Offset %llu is outside the file '%s'",
|
||||
off, filename);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
assert(off < stats.st_size);
|
||||
|
||||
if (off + count > (size_t)stats.st_size)
|
||||
count = stats.st_size - off;
|
||||
|
||||
|
||||
452
zipl/src/envblk.c
Normal file
452
zipl/src/envblk.c
Normal file
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* zipl - zSeries Initial Program Loader tool
|
||||
*
|
||||
* Functions to manipulate with environment block
|
||||
*
|
||||
* Copyright IBM Corp. 2020
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "bootmap.h"
|
||||
#include "envblk.h"
|
||||
#include "error.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* from linux/fs.h */
|
||||
#define FIGETBSZ _IO(0x00, 2)
|
||||
|
||||
void envblk_create_blank(char *envblk, int envblk_len)
|
||||
{
|
||||
memcpy(envblk, ZIPL_ENVBLK_SIGNATURE,
|
||||
sizeof(ZIPL_ENVBLK_SIGNATURE) - 1);
|
||||
memset(envblk + sizeof(ZIPL_ENVBLK_SIGNATURE) - 1, '\0',
|
||||
envblk_len - sizeof(ZIPL_ENVBLK_SIGNATURE) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out environment block location.
|
||||
* FD: bootmap file descriptor.
|
||||
* On success the searched location is saved in variable pointed out by OFF
|
||||
*/
|
||||
int envblk_offset_get(int fd, off_t *off)
|
||||
{
|
||||
struct bootmap_header bh;
|
||||
|
||||
if (bootmap_header_read(fd, &bh)) {
|
||||
error_reason("Could not read bootmap_header");
|
||||
return -1;
|
||||
}
|
||||
*off = bh.envblk_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save environment block location specified by OFF
|
||||
* FD: bootmap file descriptor.
|
||||
* On success the location is saved in the bootmap header.
|
||||
*/
|
||||
int envblk_offset_set(int fd, off_t off)
|
||||
{
|
||||
struct bootmap_header bh;
|
||||
|
||||
if (bootmap_header_read(fd, &bh)) {
|
||||
error_reason("Could not read bootmap header");
|
||||
return -1;
|
||||
}
|
||||
bh.envblk_offset = off;
|
||||
|
||||
if (bootmap_header_write(fd, &bh)) {
|
||||
error_reason("Could not write bootmap header");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out environment block size.
|
||||
* FD: bootmap file descriptor.
|
||||
* On success the searched size is stored in RESULT
|
||||
*/
|
||||
int envblk_size_get(int fd, int *result)
|
||||
{
|
||||
if (ioctl(fd, FIGETBSZ, result) == -1) {
|
||||
error_reason(strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LINE_HASH_SIZE (16)
|
||||
|
||||
/**
|
||||
* Calculate hash function of "environment line"
|
||||
*
|
||||
* LINE: pointer to a string, containing NANE=VALUE
|
||||
* LEN: length of the NAME with trailing delimiter "="
|
||||
*/
|
||||
static unsigned int linehash(char *line, int len, unsigned int hash_size)
|
||||
{
|
||||
unsigned int sum = 0;
|
||||
|
||||
while (len) {
|
||||
sum += 5 * *(line++);
|
||||
len--;
|
||||
}
|
||||
return sum % hash_size;
|
||||
}
|
||||
|
||||
struct line_hash_entry {
|
||||
struct line_hash_entry *next;
|
||||
char *line; /* pointer to an "environment line",
|
||||
* a string containing NAME=VALUE with
|
||||
* optional trailing end-of-line symbol
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if @name meets the requirements for shell environment variables
|
||||
* (IEEE Std 1003.1-2001), mitigated with lowercase letter allowance
|
||||
*
|
||||
* Return 0, if it meets, and 1 otherwise
|
||||
*/
|
||||
int envblk_check_name(char *name, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len == 0)
|
||||
return 1;
|
||||
if (!isalpha(name[0]) && name[0] != '_')
|
||||
return 1;
|
||||
for (i = 1; i < len; i++)
|
||||
if (!isalpha(name[i]) && !isdigit(name[i]) && name[i] != '_')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add environment line to hash table
|
||||
*
|
||||
* LINE: pointer to a string containing NAME=VALUE
|
||||
* LEN: length of NAME with trailing delimiter "="
|
||||
*/
|
||||
static int hash_table_add(struct line_hash_entry **table, char *line, int len)
|
||||
{
|
||||
unsigned int hash;
|
||||
struct line_hash_entry *new;
|
||||
|
||||
new = malloc(sizeof(*new));
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
memset(new, 0, sizeof(*new));
|
||||
new->line = misc_strdup(line);
|
||||
if (!new->line) {
|
||||
free(new);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hash = linehash(new->line, len, LINE_HASH_SIZE);
|
||||
new->next = table[hash];
|
||||
table[hash] = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find environment line in the hash table by name
|
||||
*
|
||||
* LINE: string contailing NAME=VALUE
|
||||
* LEN: length of the NAME with trailing delimiter "="
|
||||
*/
|
||||
struct line_hash_entry *hash_table_find(struct line_hash_entry **table,
|
||||
char *name, size_t len)
|
||||
{
|
||||
struct line_hash_entry *item;
|
||||
|
||||
item = table[linehash(name, len, LINE_HASH_SIZE)];
|
||||
while (item) {
|
||||
if (!strncmp(item->line, name, len))
|
||||
return item;
|
||||
item = item->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int hash_entry_replace(struct line_hash_entry *item, char *name,
|
||||
int *offset)
|
||||
{
|
||||
char *dup;
|
||||
|
||||
dup = misc_strdup(name);
|
||||
if (!dup)
|
||||
return -ENOMEM;
|
||||
*offset -= strlen(item->line);
|
||||
free(item->line);
|
||||
item->line = dup;
|
||||
*offset += strlen(item->line);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan hash table TABLE, and call ACTOR for each its entry.
|
||||
* The ACTOR is allowed even to release the entry.
|
||||
*/
|
||||
static void hash_table_scan(struct line_hash_entry **table,
|
||||
void (*actor)(struct line_hash_entry *entry))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LINE_HASH_SIZE; i++) {
|
||||
struct line_hash_entry *item = table[i];
|
||||
|
||||
while (item) {
|
||||
struct line_hash_entry *next = item->next;
|
||||
|
||||
actor(item);
|
||||
item = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hash_entry_free(struct line_hash_entry *this)
|
||||
{
|
||||
free(this->line);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static void hash_table_free(struct line_hash_entry **table)
|
||||
{
|
||||
hash_table_scan(table, hash_entry_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan hash table TABLE, and for each its entry copy its line to the
|
||||
* in-memory environment block specified by DST at the offset OFF.
|
||||
* Insert end-of-line symbol, if needed. The caller should guarantee
|
||||
* enough space in the buffer DST
|
||||
*/
|
||||
static void hash_table_flush(struct line_hash_entry **table, char *dst,
|
||||
int off)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LINE_HASH_SIZE; i++) {
|
||||
struct line_hash_entry *item = table[i];
|
||||
|
||||
while (item) {
|
||||
int str_len;
|
||||
|
||||
str_len = strlen(item->line);
|
||||
memcpy(dst + off, item->line, str_len);
|
||||
off += str_len;
|
||||
if (dst[off - 1] != '\n') {
|
||||
dst[off] = '\n';
|
||||
off += 1;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a zIPL environment line into hash table.
|
||||
*
|
||||
* Identify a name in the line THIS which contains a pair NAME=VALUE, and
|
||||
* look for an entry in the hash table TABLE with a similar name. If such
|
||||
* entry exists, then replace the line in that entry with the new one
|
||||
* specified by THIS. Othewise, insert a new entry to the hash table.
|
||||
*
|
||||
* THIS: pointer to a NULL-terminated string, which contains the line to
|
||||
* be imported. If the line was successfully imported, and no line with the
|
||||
* same NAME was added before, then return 0.
|
||||
* If the line should be ignored, or it replaced previously added line with
|
||||
* the same NAME, then return > 0. On errors return < 0.
|
||||
*/
|
||||
static int import_one_line(char *this, struct line_hash_entry **table,
|
||||
int *offset)
|
||||
{
|
||||
struct line_hash_entry *item;
|
||||
char *p;
|
||||
|
||||
if (*this == '#')
|
||||
/* Ignore "commented" line */
|
||||
return 1;
|
||||
|
||||
p = strchr(this, '=');
|
||||
if (p == NULL || p == this)
|
||||
/* Could not identify NAME in the line. Ignore */
|
||||
return 1;
|
||||
if (envblk_check_name(this, p - this)) {
|
||||
error_reason("Unacceptable name '%.*s'", p - this, this);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* Try to find an entry with similar NAME.
|
||||
*/
|
||||
item = hash_table_find(table, this, p - this + 1);
|
||||
|
||||
return item != NULL ? hash_entry_replace(item, this, offset) :
|
||||
hash_table_add(table, this, p - this + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import environment line-by-line from a regular file specified
|
||||
* by its name FROM_FILE to a pre-allocated buffer TO_BUF. Ignore
|
||||
* malformed, or "commented" lines. If the file doesn't end with
|
||||
* end-of-line symbol, then append that symbol in the destination
|
||||
* buffer. Return 0 on success.
|
||||
*
|
||||
* ENVBLK_SIZE: size of the destination buffer TO_BUF.
|
||||
*/
|
||||
int envblk_import(char *from_file, char *to_buf, int envblk_size)
|
||||
{
|
||||
const char *err_prefix = "Failed to import environment file";
|
||||
struct line_hash_entry *table[LINE_HASH_SIZE];
|
||||
unsigned int lines_imported = 0;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
FILE *stream;
|
||||
ssize_t read;
|
||||
int ret = 0;
|
||||
int offset;
|
||||
|
||||
stream = fopen(from_file, "r");
|
||||
if (stream == NULL)
|
||||
return 0;
|
||||
|
||||
memset(table, 0, LINE_HASH_SIZE*sizeof(void *));
|
||||
offset = sizeof(ZIPL_ENVBLK_SIGNATURE) - 1;
|
||||
|
||||
while ((read = getline(&line, &len, stream)) != -1) {
|
||||
if (read > envblk_size - offset) {
|
||||
error_reason("%s %s: maximal size (%d) exceeded",
|
||||
err_prefix, from_file,
|
||||
ENVBLK_MAX_IMPORT_SIZE(envblk_size));
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (read < 2)
|
||||
/* malformed line. Ignored */
|
||||
continue;
|
||||
if (line[read - 1] != '\n' && read == envblk_size - offset) {
|
||||
/*
|
||||
* file's tail doesn't contain end-of-line symbol at
|
||||
* the end, whereas there is no enough space in the
|
||||
* destination buffer to insert that symbol, which is
|
||||
* mandatory according to the environment block format
|
||||
*/
|
||||
error_reason("%s %s: maximal size (%d) exceeded",
|
||||
err_prefix, from_file,
|
||||
ENVBLK_MAX_IMPORT_SIZE(envblk_size));
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = import_one_line(line, table, &offset);
|
||||
if (ret < 0) {
|
||||
/* error */
|
||||
error_text("%s %s", err_prefix, from_file);
|
||||
break;
|
||||
} else if (ret > 0) {
|
||||
/*
|
||||
* either this line was ignored, or previously
|
||||
* imported line was overwritten by it
|
||||
*/
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
if (lines_imported >= ENVBLK_MAX_LINES) {
|
||||
error_reason("%s %s: maximum number of lines (%d) exceeded",
|
||||
err_prefix, from_file, ENVBLK_MAX_LINES);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
offset += read;
|
||||
lines_imported++;
|
||||
}
|
||||
hash_table_flush(table, to_buf, sizeof(ZIPL_ENVBLK_SIGNATURE) - 1);
|
||||
hash_table_free(table);
|
||||
free(line);
|
||||
fclose(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *envblk_next_line(char *s, const char *end)
|
||||
{
|
||||
while (s < end) {
|
||||
if (*s == '\n')
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
return s + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan installed environment block and call ACTOR for each found NAME.
|
||||
* Return -1 on corrupted environment blocks. Otherwise, return 0
|
||||
*/
|
||||
int envblk_scan(char *envblk, unsigned int envblk_size,
|
||||
void (*actor)(char *name))
|
||||
{
|
||||
unsigned int lines_scanned = 0;
|
||||
const char *reason;
|
||||
char *s, *end;
|
||||
char *name;
|
||||
|
||||
s = envblk + sizeof(ZIPL_ENVBLK_SIGNATURE) - 1;
|
||||
end = envblk + envblk_size;
|
||||
|
||||
while (s < end && *s != 0) {
|
||||
if (lines_scanned > ENVBLK_MAX_LINES) {
|
||||
reason = "maximum number of lines exceeded";
|
||||
goto corrupted;
|
||||
}
|
||||
name = s;
|
||||
while (s < end && *s != '=')
|
||||
s++;
|
||||
if (s == end) {
|
||||
/* delimiter "=" not found */
|
||||
reason = "missed delimiter";
|
||||
goto corrupted;
|
||||
}
|
||||
/* here @s points to "=" */
|
||||
s++;
|
||||
|
||||
while (s < end && *s != '\n')
|
||||
s++;
|
||||
if (s == end) {
|
||||
/* end of line not found */
|
||||
reason = "missed EOL";
|
||||
goto corrupted;
|
||||
}
|
||||
*s = '\0';
|
||||
actor(name);
|
||||
*s = '\n';
|
||||
lines_scanned++;
|
||||
s = envblk_next_line(s, end);
|
||||
}
|
||||
return 0;
|
||||
corrupted:
|
||||
error_reason("Found corrupted environment block (%s) - please run zipl",
|
||||
reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void print_name_value(char *this)
|
||||
{
|
||||
printf(" %s\n", this);
|
||||
}
|
||||
|
||||
void envblk_print(char *envblk, unsigned int envblk_size)
|
||||
{
|
||||
printf("Environment block content:\n");
|
||||
envblk_scan(envblk, envblk_size, print_name_value);
|
||||
}
|
||||
101
zipl/src/job.c
101
zipl/src/job.c
@@ -14,6 +14,7 @@
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include "misc.h"
|
||||
#include "scan.h"
|
||||
#include "zipl.h"
|
||||
#include "envblk.h"
|
||||
|
||||
/* Command line options */
|
||||
static struct option options[] = {
|
||||
@@ -37,6 +39,7 @@ static struct option options[] = {
|
||||
{ "targetgeometry", required_argument, NULL, 0xac},
|
||||
{ "targetblocksize", required_argument, NULL, 0xad},
|
||||
{ "targetoffset", required_argument, NULL, 0xae},
|
||||
{ "environment", required_argument, NULL, 0xaf},
|
||||
{ "image", required_argument, NULL, 'i'},
|
||||
{ "ramdisk", required_argument, NULL, 'r'},
|
||||
{ "parmfile", required_argument, NULL, 'p'},
|
||||
@@ -73,6 +76,7 @@ static const char *zipl_conf[] = {
|
||||
struct command_line {
|
||||
char* data[SCAN_KEYWORD_NUM];
|
||||
char* config;
|
||||
char *envblk_import_hint;
|
||||
char *blsdir;
|
||||
char* menu;
|
||||
char* section;
|
||||
@@ -87,7 +91,6 @@ struct command_line {
|
||||
enum scan_section_type type;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
store_option(struct command_line* cmdline, enum scan_keyword_id keyword,
|
||||
char* value)
|
||||
@@ -211,6 +214,13 @@ get_command_line(int argc, char* argv[], struct command_line* line)
|
||||
rc = store_option(&cmdline, scan_keyword_targetoffset,
|
||||
optarg);
|
||||
break;
|
||||
case 0xaf:
|
||||
if (cmdline.envblk_import_hint != NULL) {
|
||||
error_reason("Option 'environment' specified more than once");
|
||||
rc = -1;
|
||||
} else
|
||||
cmdline.envblk_import_hint = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
is_keyword = 1;
|
||||
rc = store_option(&cmdline, scan_keyword_tape,
|
||||
@@ -351,6 +361,12 @@ free_target_data(struct job_target_data* data)
|
||||
free(data->targetbase);
|
||||
}
|
||||
|
||||
static void
|
||||
free_envblk_data(struct job_envblk_data *data)
|
||||
{
|
||||
free(data->buf);
|
||||
}
|
||||
|
||||
static void
|
||||
free_ipl_data(struct job_ipl_data* data)
|
||||
{
|
||||
@@ -444,6 +460,7 @@ job_free(struct job_data* job)
|
||||
if (job->target.bootmap_dir != NULL)
|
||||
free(job->target.bootmap_dir);
|
||||
free_target_data(&job->target);
|
||||
free_envblk_data(&job->envblk);
|
||||
if (job->name != NULL)
|
||||
free(job->name);
|
||||
switch (job->id) {
|
||||
@@ -480,7 +497,7 @@ struct component_loc {
|
||||
};
|
||||
|
||||
static int
|
||||
set_cl_element(struct component_loc *cl, char *name, char *filename,
|
||||
set_cl_element(struct component_loc *cl, char *name, const char *filename,
|
||||
address_t *addrp, size_t size, off_t off, off_t align)
|
||||
{
|
||||
struct stat stats;
|
||||
@@ -528,17 +545,16 @@ sort_cl_array(struct component_loc* cl, int elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
|
||||
int *nump)
|
||||
int *nump, struct job_envblk_data *envblk)
|
||||
{
|
||||
struct component_loc *cl;
|
||||
int num;
|
||||
int rc;
|
||||
|
||||
/* Get memory for image, parmline, ramdisk */
|
||||
cl = misc_calloc(3, sizeof(struct component_loc));
|
||||
/* Get memory for image, parmline, ramdisk and environment block */
|
||||
cl = misc_calloc(4, sizeof(struct component_loc));
|
||||
if (cl == NULL)
|
||||
return -1;
|
||||
/* Fill in component data */
|
||||
@@ -561,6 +577,12 @@ get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
|
||||
if (rc)
|
||||
goto error;
|
||||
}
|
||||
rc = set_cl_element(&cl[num++], "environment block",
|
||||
NULL,
|
||||
&ipl->envblk_addr, envblk->size, 0,
|
||||
MAXIMUM_PHYSICAL_BLOCKSIZE);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
*clp = cl;
|
||||
*nump = num;
|
||||
@@ -753,7 +775,8 @@ finalize_component_address_data(struct component_loc *cl, int num,
|
||||
|
||||
|
||||
static int
|
||||
finalize_ipl_address_data(struct job_ipl_data* ipl, char *name)
|
||||
finalize_ipl_address_data(struct job_ipl_data *ipl, char *name,
|
||||
struct job_envblk_data *envblk)
|
||||
{
|
||||
unsigned long address_limit;
|
||||
struct component_loc *cl;
|
||||
@@ -762,7 +785,7 @@ finalize_ipl_address_data(struct job_ipl_data* ipl, char *name)
|
||||
|
||||
address_limit = ipl->is_kdump ?
|
||||
MIN(util_arch_hsa_maxsize(), ADDRESS_LIMIT) : ADDRESS_LIMIT;
|
||||
rc = get_ipl_components(ipl, &cl, &num);
|
||||
rc = get_ipl_components(ipl, &cl, &num, envblk);
|
||||
if (rc)
|
||||
return rc;
|
||||
sort_cl_array(cl, num);
|
||||
@@ -828,7 +851,8 @@ out_free:
|
||||
|
||||
|
||||
static int
|
||||
check_job_ipl_data(struct job_ipl_data *ipl, char* name)
|
||||
check_job_ipl_data(struct job_ipl_data *ipl, char *name,
|
||||
struct job_envblk_data *envblk)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -856,7 +880,7 @@ check_job_ipl_data(struct job_ipl_data *ipl, char* name)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return finalize_ipl_address_data(ipl, name);
|
||||
return finalize_ipl_address_data(ipl, name, envblk);
|
||||
}
|
||||
|
||||
|
||||
@@ -935,7 +959,7 @@ check_job_dump_images(struct job_dump_data* dump, char* name)
|
||||
|
||||
|
||||
static int
|
||||
check_job_menu_data(struct job_menu_data* menu)
|
||||
check_job_menu_data(struct job_menu_data *menu, struct job_envblk_data *envblk)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
@@ -944,7 +968,8 @@ check_job_menu_data(struct job_menu_data* menu)
|
||||
switch (menu->entry[i].id) {
|
||||
case job_ipl:
|
||||
rc = check_job_ipl_data(&menu->entry[i].data.ipl,
|
||||
menu->entry[i].name);
|
||||
menu->entry[i].name,
|
||||
envblk);
|
||||
if (rc)
|
||||
return rc;
|
||||
break;
|
||||
@@ -1110,10 +1135,11 @@ check_job_data(struct job_data* job)
|
||||
rc = 0;
|
||||
break;
|
||||
case job_ipl:
|
||||
rc = check_job_ipl_data(&job->data.ipl, job->name);
|
||||
rc = check_job_ipl_data(&job->data.ipl, job->name,
|
||||
&job->envblk);
|
||||
break;
|
||||
case job_menu:
|
||||
rc = check_job_menu_data(&job->data.menu);
|
||||
rc = check_job_menu_data(&job->data.menu, &job->envblk);
|
||||
break;
|
||||
case job_segment:
|
||||
rc = check_job_segment_data(&job->data.segment, job->name);
|
||||
@@ -1372,6 +1398,9 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
||||
&job->data.ipl.parm_addr, section);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Fill in environment block */
|
||||
job->data.ipl.envblk_addr = UNSPECIFIED_ADDRESS;
|
||||
|
||||
/* Fill in name and address of ramdisk file */
|
||||
if (data[(int) scan_keyword_ramdisk] != NULL) {
|
||||
job->data.ipl.ramdisk =
|
||||
@@ -1898,6 +1927,45 @@ get_job_from_config_file(struct command_line* cmdline, struct job_data* job)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int get_job_envblk_data(struct job_data *job, char *import_hint)
|
||||
{
|
||||
struct job_envblk_data *data = &job->envblk;
|
||||
int fd;
|
||||
|
||||
switch (job->id) {
|
||||
case job_ipl:
|
||||
case job_menu:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
fd = open(job->target.bootmap_dir, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
error_reason(strerror(errno));
|
||||
error_text("Could not open bootmap dir");
|
||||
return -1;
|
||||
}
|
||||
if (envblk_size_get(fd, &data->size)) {
|
||||
close(fd);
|
||||
error_text("Could not get environment block size");
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
data->buf = misc_malloc(data->size);
|
||||
if (data->buf == NULL) {
|
||||
error_text("Could not allocate environment block");
|
||||
return -1;
|
||||
}
|
||||
envblk_create_blank(data->buf, data->size);
|
||||
|
||||
if (envblk_import(import_hint ?: ENVBLK_DEFAULT_IMPORT_SOURCE,
|
||||
data->buf, data->size)) {
|
||||
free(data->buf);
|
||||
data->buf = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
job_get(int argc, char* argv[], struct job_data** data)
|
||||
@@ -1946,6 +2014,11 @@ job_get(int argc, char* argv[], struct job_data** data)
|
||||
else if (job->id != job_menu && job->is_secure == SECURE_BOOT_UNDEFINED)
|
||||
job->is_secure = SECURE_BOOT_AUTO;
|
||||
|
||||
rc = get_job_envblk_data(job, cmdline.envblk_import_hint);
|
||||
if (rc) {
|
||||
job_free(job);
|
||||
return -1;
|
||||
}
|
||||
/* Check job data for validity */
|
||||
rc = check_job_data(job);
|
||||
if (rc) {
|
||||
|
||||
Reference in New Issue
Block a user