mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zipl: Support command lines longer than 896 bytes in bootloader
This adds support for long command lines. The boot loader stages will no longer use a fixed limit when copying the command line, but will use the maximum length from the kernel image that is being loaded. Signed-off-by: Sven Schnelle <svens@linux.ibm.com> Reviewed-by: Stefan Haberland <sth@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
bb8f17a7da
commit
1627c6a39f
@@ -23,6 +23,7 @@
|
||||
#define INITRD_SIZE _AC(0x10410, UL)
|
||||
#define OLDMEM_BASE _AC(0x10418, UL)
|
||||
#define OLDMEM_SIZE _AC(0x10420, UL)
|
||||
#define MAX_COMMAND_LINE_SIZE _AC(0x10430, UL)
|
||||
#define COMMAND_LINE _AC(0x10480, UL)
|
||||
|
||||
/* Parameter sizes */
|
||||
|
||||
@@ -232,7 +232,8 @@ static void parse_envblk(struct env_hash_entry *items,
|
||||
* CMDL_LEN: length of the command line to be processed
|
||||
* BUCKETS: hash table of pairs (NAME, VALUE)
|
||||
*/
|
||||
void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
|
||||
void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len,
|
||||
unsigned int max_len)
|
||||
{
|
||||
struct env_hash_entry *item;
|
||||
char empty_str = 0;
|
||||
@@ -282,7 +283,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
|
||||
*/
|
||||
len = strlen(val);
|
||||
|
||||
if (cmdl_len + len - (end - start + 1) >= LEGACY_COMMAND_LINE_SIZE)
|
||||
if (cmdl_len + len - (end - start + 1) >= max_len)
|
||||
/* VALUE doesn't fit */
|
||||
break;
|
||||
/*
|
||||
@@ -306,7 +307,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
|
||||
/**
|
||||
* LEN: length of the command line to be processed
|
||||
*/
|
||||
static void handle_environment(unsigned int len)
|
||||
static void handle_environment(unsigned int len, unsigned int max_len)
|
||||
{
|
||||
struct env_hash_entry *buckets[STR_HASH_SIZE];
|
||||
struct env_hash_entry *items;
|
||||
@@ -326,7 +327,7 @@ static void handle_environment(unsigned int len)
|
||||
* find environment variables in the command line and
|
||||
* replace them with their values as found in the hash table
|
||||
*/
|
||||
process_parm_line(buckets, len);
|
||||
process_parm_line(buckets, len, max_len);
|
||||
free_page((unsigned long)items);
|
||||
}
|
||||
|
||||
@@ -350,14 +351,18 @@ static void setup_cmdline(void)
|
||||
char *cextra = (char *)COMMAND_LINE_EXTRA;
|
||||
char *cmdline = (char *)COMMAND_LINE;
|
||||
unsigned int cmdline_len = 0;
|
||||
unsigned int max_cmdline_len = *(unsigned long *)MAX_COMMAND_LINE_SIZE;
|
||||
|
||||
if (!max_cmdline_len)
|
||||
max_cmdline_len = LEGACY_COMMAND_LINE_SIZE;
|
||||
|
||||
/* if valid command line is given, copy it into new kernel space */
|
||||
if (_stage3_parms.parm_addr != UNSPECIFIED_ADDRESS) {
|
||||
strlcpy(cmdline, (void *)(unsigned long *)_stage3_parms.parm_addr,
|
||||
LEGACY_COMMAND_LINE_SIZE);
|
||||
max_cmdline_len);
|
||||
}
|
||||
/* determine length of original parm line */
|
||||
cmdline_len = MIN(strlen(cmdline), LEGACY_COMMAND_LINE_SIZE - 1);
|
||||
cmdline_len = MIN((unsigned int)strlen(cmdline), max_cmdline_len - 1);
|
||||
|
||||
/* convert extra parameter to ascii */
|
||||
if (!_stage3_parms.extra_parm || !*cextra)
|
||||
@@ -374,15 +379,15 @@ static void setup_cmdline(void)
|
||||
* else append
|
||||
*/
|
||||
if (*cextra == 0x3d) {
|
||||
strlcpy(cmdline, cextra+1, LEGACY_COMMAND_LINE_SIZE);
|
||||
} else if (*cextra && cmdline_len + 1 <= LEGACY_COMMAND_LINE_SIZE - 1) {
|
||||
strlcpy(cmdline, cextra+1, max_cmdline_len);
|
||||
} else if (*cextra && cmdline_len + 1 <= max_cmdline_len - 1) {
|
||||
/* add blank */
|
||||
cmdline[cmdline_len++] = 0x20;
|
||||
strlcpy(cmdline + cmdline_len, cextra, LEGACY_COMMAND_LINE_SIZE - cmdline_len);
|
||||
strlcpy(cmdline + cmdline_len, cextra, max_cmdline_len - cmdline_len);
|
||||
}
|
||||
|
||||
noextra:
|
||||
handle_environment(strlen(cmdline));
|
||||
handle_environment(strlen(cmdline), max_cmdline_len);
|
||||
}
|
||||
|
||||
void start(void)
|
||||
|
||||
@@ -249,31 +249,35 @@ iplstart:
|
||||
clc 0(3,%r4),.L_eof # if it is EOFx
|
||||
bz .Lagain1 # skip dateset trailer
|
||||
|
||||
chi %r2,LEGACY_COMMAND_LINE_SIZE-1 # truncate if line too long
|
||||
lt %r3,MAX_COMMAND_LINE_SIZE-PARMAREA+4(%r12)
|
||||
jnz 0f
|
||||
lhi %r3,LEGACY_COMMAND_LINE_SIZE
|
||||
0: cr %r2,%r3 # truncate if line too long
|
||||
bnh .Lnotrunc
|
||||
la %r2,LEGACY_COMMAND_LINE_SIZE-1
|
||||
lr %r2,%r3
|
||||
.Lnotrunc:
|
||||
|
||||
la %r5,0(%r4,%r2) # search for EBCDIC chars
|
||||
lr %r3,%r2
|
||||
ahi %r5,-1
|
||||
lr %r6,%r2
|
||||
.Lidebc:
|
||||
tm 0(%r5),0x80 # high order bit set ?
|
||||
bo .Ldocv # yes -> convert from EBCDIC
|
||||
ahi %r5,-1
|
||||
bct %r3,.Lidebc
|
||||
bct %r6,.Lidebc
|
||||
b .Lnocv
|
||||
.Ldocv:
|
||||
la %r3,_ebcasc
|
||||
tr 0(256,%r4),0(%r3) # convert parameters to ascii
|
||||
tr 256(256,%r4),0(%r3)
|
||||
tr 512(256,%r4),0(%r3)
|
||||
tr 768(127,%r4),0(%r3)
|
||||
lr %r6,%r2
|
||||
la %r5,_ebcasc
|
||||
0: tr 0(1,%r4),0(%r5)
|
||||
ahi %r4,1
|
||||
brct %r6,0b
|
||||
l %r4,_parm_addr+4
|
||||
.Lnocv:
|
||||
la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
|
||||
mvc 0(256,%r3),0(%r4)
|
||||
mvc 256(256,%r3),256(%r4)
|
||||
mvc 512(256,%r3),512(%r4)
|
||||
mvc 768(127,%r3),768(%r4)
|
||||
lr %r5,%r2
|
||||
ahi %r5,-1
|
||||
la %r6,COMMAND_LINE-PARMAREA(%r12)
|
||||
lr %r7,%r2
|
||||
mvcl %r6,%r4
|
||||
slr %r0,%r0
|
||||
b .Lcntlp
|
||||
.Ldelspc:
|
||||
|
||||
Reference in New Issue
Block a user