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:
Sven Schnelle
2021-11-04 12:21:28 +01:00
committed by Jan Höppner
parent bb8f17a7da
commit 1627c6a39f
3 changed files with 35 additions and 25 deletions

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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: