[syslinux:elflink] elflink: add more change as show below
syslinux-bot for Feng Tang
feng.tang at intel.com
Thu Aug 12 21:03:55 PDT 2010
Commit-ID: 3400a8754214f4cd69d49d85c0396665d7a6415f
Gitweb: http://syslinux.zytor.com/commit/3400a8754214f4cd69d49d85c0396665d7a6415f
Author: Feng Tang <feng.tang at intel.com>
AuthorDate: Wed, 14 Jul 2010 10:57:18 +0800
Committer: Feng Tang <feng.tang at intel.com>
CommitDate: Tue, 20 Jul 2010 11:10:04 +0800
elflink: add more change as show below
com32/lib/chdir.c
com32/lib/getcwd.c
com32/lib/getopt.c
com32/lib/pci/scan.c
com32/lib/sys/farcall.c
com32/lib/sys/times.c
com32/lib/sys/vesa/background.c
com32/lib/sys/vesa/screencpy.c
com32/lib/vdprintf.c
com32/rosh/rosh.c
com32/rosh/rosh.h
com32/sysdump/backend.h
com32/sysdump/be_tftp.c
com32/sysdump/main.c
com32/sysdump/memmap.c
com32/sysdump/sysdump.h
com32/sysdump/vesa.c
doc/comboot.txt
doc/extlinux.txt
doc/gpt.txt
doc/memdisk.txt
doc/menu.txt
doc/syslinux.txt
---
com32/lib/chdir.c | 10 +-
com32/lib/getcwd.c | 23 +-
com32/lib/getopt.c | 117 +++--
com32/lib/pci/scan.c | 8 +-
com32/lib/sys/farcall.c | 15 +-
com32/lib/sys/times.c | 8 +-
com32/lib/sys/vesa/background.c | 4 +-
com32/lib/sys/vesa/screencpy.c | 7 +-
com32/lib/vdprintf.c | 7 +-
com32/rosh/rosh.c | 913 ++++++++++++++++++++++++++-------------
com32/rosh/rosh.h | 164 +++++--
com32/sysdump/backend.h | 1 +
com32/sysdump/be_tftp.c | 53 ++-
com32/sysdump/main.c | 2 +
com32/sysdump/memmap.c | 6 +-
com32/sysdump/sysdump.h | 1 +
com32/sysdump/vesa.c | 7 +-
doc/comboot.txt | 21 +-
doc/extlinux.txt | 6 +-
doc/gpt.txt | 53 +--
doc/memdisk.txt | 6 +-
doc/menu.txt | 22 +-
doc/syslinux.txt | 17 +-
23 files changed, 966 insertions(+), 505 deletions(-)
diff --git a/com32/lib/chdir.c b/com32/lib/chdir.c
index 6a365f3..00670e3 100644
--- a/com32/lib/chdir.c
+++ b/com32/lib/chdir.c
@@ -6,12 +6,10 @@
#include <stdio.h>
#include <errno.h>
+#include <com32.h>
+#include <syslinux/pmapi.h>
+
int chdir(const char *path)
{
- /* Actually implement something here... */
-
- (void)path;
-
- errno = ENOSYS;
- return -1;
+ return __com32.cs_pm->chdir(path);
}
diff --git a/com32/lib/getcwd.c b/com32/lib/getcwd.c
index 38fae52..5ce62ec 100644
--- a/com32/lib/getcwd.c
+++ b/com32/lib/getcwd.c
@@ -2,29 +2,10 @@
* getcwd.c
*/
-#include <syslinux/config.h>
-#include <klibc/compiler.h>
#include <com32.h>
-
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
+#include <syslinux/pmapi.h>
char *getcwd(char *buf, size_t size)
{
- static com32sys_t reg;
- char *pwdstr, *ret;
-
- reg.eax.w[0] = 0x001f;
- __intcall(0x22, ®, ®);
- pwdstr = MK_PTR(reg.es, reg.ebx.w[0]);
- if ((strlen(pwdstr) < size) && (buf != NULL)) {
- strcpy(buf, pwdstr);
- ret = buf;
- } else {
- ret = NULL;
- errno = ERANGE;
- }
- return ret;
+ return __com32.cs_pm->getcwd(buf, size);
}
diff --git a/com32/lib/getopt.c b/com32/lib/getopt.c
index 5e9b7c6..806735d 100644
--- a/com32/lib/getopt.c
+++ b/com32/lib/getopt.c
@@ -9,64 +9,89 @@
#include <string.h>
char *optarg;
-int optind = 1;
-int opterr, optopt;
-static const char *__optptr;
+int optind, opterr, optopt;
+static struct getopt_private_state {
+ const char *optptr;
+ const char *last_optstring;
+ char *const *last_argv;
+} pvt;
int getopt(int argc, char *const *argv, const char *optstring)
{
- const char *carg = argv[optind];
- const char *osptr;
- int opt;
+ const char *carg;
+ const char *osptr;
+ int opt;
- /* We don't actually need argc */
- (void)argc;
+ /* getopt() relies on a number of different global state
+ variables, which can make this really confusing if there is
+ more than one use of getopt() in the same program. This
+ attempts to detect that situation by detecting if the
+ "optstring" or "argv" argument have changed since last time
+ we were called; if so, reinitialize the query state. */
- /* First, eliminate all non-option cases */
-
- if (!carg || carg[0] != '-' || !carg[1]) {
- return -1;
- }
+ if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+ optind < 1 || optind > argc) {
+ /* optind doesn't match the current query */
+ pvt.last_optstring = optstring;
+ pvt.last_argv = argv;
+ optind = 1;
+ pvt.optptr = NULL;
+ }
- if (carg[1] == '-' && !carg[2]) {
- optind++;
- return -1;
- }
+ carg = argv[optind];
- if ((uintptr_t) (__optptr - carg) > (uintptr_t) strlen(carg))
- __optptr = carg + 1; /* Someone frobbed optind, change to new opt. */
+ /* First, eliminate all non-option cases */
- opt = *__optptr++;
+ if (!carg || carg[0] != '-' || !carg[1]) {
+ return -1;
+ }
- if (opt != ':' && (osptr = strchr(optstring, opt))) {
- if (osptr[1] == ':') {
- if (*__optptr) {
- /* Argument-taking option with attached argument */
- optarg = (char *)__optptr;
+ if (carg[1] == '-' && !carg[2]) {
optind++;
- } else {
- /* Argument-taking option with non-attached argument */
- if (argv[optind + 1]) {
- optarg = (char *)argv[optind + 1];
- optind += 2;
+ return -1;
+ }
+
+ if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+ /* Someone frobbed optind, change to new opt. */
+ pvt.optptr = carg + 1;
+ }
+
+ opt = *pvt.optptr++;
+
+ if (opt != ':' && (osptr = strchr(optstring, opt))) {
+ if (osptr[1] == ':') {
+ if (*pvt.optptr) {
+ /* Argument-taking option with attached
+ argument */
+ optarg = (char *)pvt.optptr;
+ optind++;
+ } else {
+ /* Argument-taking option with non-attached
+ argument */
+ if (argv[optind + 1]) {
+ optarg = (char *)argv[optind+1];
+ optind += 2;
+ } else {
+ /* Missing argument */
+ optind++;
+ return (optstring[0] == ':')
+ ? ':' : '?';
+ }
+ }
+ return opt;
} else {
- /* Missing argument */
- return (optstring[0] == ':') ? ':' : '?';
+ /* Non-argument-taking option */
+ /* pvt.optptr will remember the exact position to
+ resume at */
+ if (!*pvt.optptr)
+ optind++;
+ return opt;
}
- }
- return opt;
} else {
- /* Non-argument-taking option */
- /* __optptr will remember the exact position to resume at */
- if (!*__optptr)
- optind++;
- return opt;
+ /* Unknown option */
+ optopt = opt;
+ if (!*pvt.optptr)
+ optind++;
+ return '?';
}
- } else {
- /* Unknown option */
- optopt = opt;
- if (!*__optptr)
- optind++;
- return '?';
- }
}
diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c
index 65d8015..2577b32 100644
--- a/com32/lib/pci/scan.c
+++ b/com32/lib/pci/scan.c
@@ -676,28 +676,28 @@ int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_pa
/* Searching for the vendor separator*/
char *temp = strstr(result,"d");
if (temp != NULL) {
- strncpy(vendor_id,result,temp-result);
+ strlcpy(vendor_id,result,temp-result);
result+=strlen(vendor_id)+1;
}
/* Searching for the product separator*/
temp = strstr(result,"sv");
if (temp != NULL) {
- strncpy(product_id,result,temp-result);
+ strlcpy(product_id,result,temp-result);
result+=strlen(product_id)+1;
}
/* Searching for the sub vendor separator*/
temp = strstr(result,"sd");
if (temp != NULL) {
- strncpy(sub_vendor_id,result,temp-result);
+ strlcpy(sub_vendor_id,result,temp-result);
result+=strlen(sub_vendor_id)+1;
}
/* Searching for the sub product separator*/
temp = strstr(result,"bc");
if (temp != NULL) {
- strncpy(sub_product_id,result,temp-result);
+ strlcpy(sub_product_id,result,temp-result);
result+=strlen(sub_product_id)+1;
}
/* That's the module name */
diff --git a/com32/lib/sys/farcall.c b/com32/lib/sys/farcall.c
index 7d195f1..988ee6d 100644
--- a/com32/lib/sys/farcall.c
+++ b/com32/lib/sys/farcall.c
@@ -4,8 +4,21 @@
#include <com32.h>
+static inline uint32_t eflags(void)
+{
+ uint32_t v;
+
+ asm volatile("pushfl ; popl %0" : "=rm" (v));
+ return v;
+}
+
void __farcall(uint16_t cs, uint16_t ip,
const com32sys_t * ireg, com32sys_t * oreg)
{
- __com32.cs_farcall((cs << 16) + ip, ireg, oreg);
+ com32sys_t xreg = *ireg;
+
+ /* Enable interrupts if and only if they are enabled in the caller */
+ xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF);
+
+ __com32.cs_farcall((cs << 16) + ip, &xreg, oreg);
}
diff --git a/com32/lib/sys/times.c b/com32/lib/sys/times.c
index 12ed671..dd063f3 100644
--- a/com32/lib/sys/times.c
+++ b/com32/lib/sys/times.c
@@ -32,13 +32,11 @@
*/
#include <sys/times.h>
-#include <inttypes.h>
+#include <syslinux/pmapi.h>
#include <com32.h>
clock_t times(struct tms * buf)
{
- (void)buf; /* Ignored */
-
- /* Should we get this via INT 1Ah? */
- return *(uint16_t *) 0x46c;
+ (void)buf;
+ return *__com32.cs_pm->ms_timer;
}
diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c
index 8d73239..9357746 100644
--- a/com32/lib/sys/vesa/background.c
+++ b/com32/lib/sys/vesa/background.c
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <minmax.h>
#include <stdbool.h>
+#include <ilog2.h>
#include <syslinux/loadfile.h>
#include "vesa.h"
#include "video.h"
@@ -255,8 +256,7 @@ int vesacon_default_background(void)
z = max(__vesa_info.mi.v_res, __vesa_info.mi.h_res) >> 1;
z = ((z*z) >> 11) - 1;
- asm("bsrl %1,%0" : "=r" (shft) : "rm" (z));
- shft++;
+ shft = ilog2(z) + 1;
for (y = 0, dy = -(__vesa_info.mi.v_res >> 1);
y < __vesa_info.mi.v_res; y++, dy++) {
diff --git a/com32/lib/sys/vesa/screencpy.c b/com32/lib/sys/vesa/screencpy.c
index 9740ea1..32dce9e 100644
--- a/com32/lib/sys/vesa/screencpy.c
+++ b/com32/lib/sys/vesa/screencpy.c
@@ -30,6 +30,7 @@
#include <klibc/compiler.h>
#include <string.h>
#include <com32.h>
+#include <ilog2.h>
#include "vesa.h"
#include "video.h"
@@ -41,12 +42,6 @@ static struct win_info {
int win_num;
} wi;
-static inline int __constfunc ilog2(unsigned int x)
-{
- asm("bsrl %1,%0" : "=r"(x) : "rm"(x));
- return x;
-}
-
void __vesacon_init_copy_to_screen(void)
{
struct vesa_mode_info *const mi = &__vesa_info.mi;
diff --git a/com32/lib/vdprintf.c b/com32/lib/vdprintf.c
index 330279b..d74f278 100644
--- a/com32/lib/vdprintf.c
+++ b/com32/lib/vdprintf.c
@@ -30,7 +30,12 @@ enum serial_port_regs {
MSR = 6,
SCR = 7,
};
-static const uint16_t debug_base = 0x03f8; /* I/O base address */
+
+#ifndef DEBUG_PORT
+# define DEBUG_PORT 0x03f8 /* I/O base address */
+#endif
+
+static const uint16_t debug_base = DEBUG_PORT;
static void debug_putc(char c)
{
diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c
index 511fdff..bf1176f 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 2008 Gene Cumm - All Rights Reserved
+ * Copyright 2008-2010 Gene Cumm - All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,22 +20,24 @@
/*
* ToDos:
- * Change functions to use pwdstr
- * In rosh_run() Reparse cmdstr relative to pwdstr
+ * rosh_ls(): sorted; then multiple columns
*/
-// #define DO_DEBUG 1
- /* Uncomment the above line for debugging output; Comment to remove */
-// #define DO_DEBUG2 1
- /* Uncomment the above line for super-debugging output; Must have regular debugging enabled; Comment to remove */
-
+/*#define DO_DEBUG 1
+//*/
+/* Uncomment the above line for debugging output; Comment to remove */
+/*#define DO_DEBUG2 1
+//*/
+/* Uncomment the above line for super-debugging output; Must have regular
+ * debugging enabled; Comment to remove.
+ */
#include "rosh.h"
#define APP_LONGNAME "Read-Only Shell"
#define APP_NAME "rosh"
#define APP_AUTHOR "Gene Cumm"
-#define APP_YEAR "2008"
-#define APP_VER "beta-b032"
+#define APP_YEAR "2010"
+#define APP_VER "beta-b062"
void rosh_version(void)
{
@@ -43,37 +45,13 @@ void rosh_version(void)
APP_AUTHOR);
}
-void rosh_help(int type)
+void print_beta(void)
{
- rosh_version();
- switch (type) {
- case 2:
- puts(rosh_help_str2);
- break;
- case 1:
- default:
- puts(rosh_help_str1);
- }
+ puts(rosh_beta_str);
+ ROSH_DEBUG("DO_DEBUG active\n");
+ ROSH_DEBUG2("DO_DEBUG2 active\n");
}
-/* Determine if a character is whitespace
- * inc input character
- * returns 0 if not whitespace
- */
-int rosh_issp(char inc)
-{
- int rv;
- switch (inc) {
- case ' ':
- case '\t':
- rv = 1;
- break;
- default:
- rv = 0;
- }
- return rv;
-} /* ros_issp */
-
/* Search a string for first non-space (' ') character, starting at ipos
* istr input string to parse
* ipos input position to start at
@@ -85,7 +63,7 @@ int rosh_search_nonsp(const char *istr, const int ipos)
curpos = ipos;
c = istr[curpos];
- while (rosh_issp(c) && c != 0)
+ while (c && isspace(c))
c = istr[++curpos];
return curpos;
}
@@ -102,7 +80,7 @@ int rosh_search_sp(const char *istr, const int ipos)
curpos = ipos;
c = istr[curpos];
- while (!(rosh_issp(c)) && c != 0)
+ while (c && !(isspace(c)))
c = istr[++curpos];
return curpos;
}
@@ -134,6 +112,37 @@ int rosh_parse_sp_1(char *dest, const char *src, const int ipos)
return epos;
}
+/* Display help
+ * type Help type
+ * cmdstr Command string
+ */
+void rosh_help(int type, const char *cmdstr)
+{
+ const char *istr;
+ istr = cmdstr;
+ switch (type) {
+ case 2:
+ istr += rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0));
+ if ((cmdstr == NULL) || (strcmp(istr, "") == 0)) {
+ rosh_version();
+ puts(rosh_help_str2);
+ } else {
+ switch (istr[0]) {
+ case 'l':
+ puts(rosh_help_ls_str);
+ break;
+ default:
+ printf(rosh_help_str_adv, istr);
+ }
+ }
+ break;
+ case 1:
+ default:
+ rosh_version();
+ puts(rosh_help_str1);
+ }
+}
+
/* Handle most/all errors
* ierrno Input Error number
* cmdstr Command being executed to cause error
@@ -143,26 +152,38 @@ void rosh_error(const int ierrno, const char *cmdstr, const char *filestr)
{
printf("--ERROR: %s '%s': ", cmdstr, filestr);
switch (ierrno) {
- case EACCES:
- printf("Access DENIED\n");
+ case 0:
+ puts("NO ERROR");
break;
case ENOENT:
- printf("not found\n");
+ puts("not found");
/* SYSLinux-3.72 COM32 API returns this for a
directory or empty file */
ROSH_COM32(" (COM32) could be a directory or empty file\n");
break;
+ case EIO:
+ puts("I/O Error");
+ break;
+ case EBADF:
+ puts("Bad File Descriptor");
+ break;
+ case EACCES:
+ puts("Access DENIED");
+ break;
case ENOTDIR:
- printf("not a directory\n");
+ puts("not a directory");
ROSH_COM32(" (COM32) could be directory\n");
break;
+ case EISDIR:
+ puts("IS a directory");
+ break;
case ENOSYS:
- printf("not implemented");
+ puts("not implemented");
break;
default:
printf("returns error; errno=%d\n", ierrno);
}
-}
+} /* rosh_error */
/* Concatenate command line arguments into one string
* cmdstr Output command string
@@ -221,34 +242,6 @@ void rosh_print_tc(struct termios *tio)
*/
/*
- * Switches console over to raw input mode. Allows get_key to get just
- * 1 key sequence (without delay or display)
- */
-void rosh_console_raw(void)
-{
-// struct termios itio, ntio;
-// tcgetattr(0, &itio);
-// rosh_print_tc(&itio);
-/* ntio = itio;
- ntio.c_lflag &= ~(ICANON|ECHO);
- tcsetattr(0, TCSAFLUSH, &ntio);*/
- console_ansi_raw(); /* Allows get_key to get just 1 key sequence
- (w/o delay or display */
-// tcgetattr(0, &ntio);
-// rosh_print_tc(&ntio);
-}
-
-/*
- * Switches back to standard getline mode.
- */
-void rosh_console_std(void)
-{
-// struct termios itio, ntio;
- console_ansi_std();
-// tcsetattr(0, TCSANOW, &itio);
-}
-
-/*
* Attempts to get a single key from the console
* returns key pressed
*/
@@ -257,37 +250,45 @@ int rosh_getkey(void)
int inc;
inc = KEY_NONE;
-// rosh_console_raw();
- while (inc == KEY_NONE) {
+ while (inc == KEY_NONE)
inc = get_key(stdin, 6000);
- }
-// rosh_console_std();
return inc;
} /* rosh_getkey */
-/* Template for command functions
- * cmdstr command string to process
- * pwdstr Present Working Directory string
- * ipwdstr Initial PWD
+/*
+ * Qualifies a filename relative to the working directory
+ * filestr Filename to qualify
+ * pwdstr working directory
+ * returns qualified file name string
*/
-void rosh_1(const char *cmdstr, const char *pwdstr, const char *ipwdstr)
+void rosh_qualify_filestr(char *filestr, const char *ifilstr,
+ const char *pwdstr)
{
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\npwd: '%s'\n", cmdstr, pwdstr, ipwdstr);
-} /* rosh_1 */
+ int filepos = 0;
+ if ((filestr) && (pwdstr) && (ifilstr)) {
+ if (ifilstr[0] != SEP) {
+ strcpy(filestr, pwdstr);
+ filepos = strlen(pwdstr);
+ if (filestr[filepos - 1] != SEP)
+ filestr[filepos++] = SEP;
+ }
+ strcpy(filestr + filepos, ifilstr);
+ ROSH_DEBUG("--'%s'\n", filestr);
+ }
+}
/* Concatenate multiple files to stdout
* cmdstr command string to process
- * pwdstr Present Working Directory string
*/
-void rosh_cat(const char *cmdstr, const char *pwdstr)
+void rosh_cat(const char *cmdstr)
{
FILE *f;
- char filestr[ROSH_PATH_SZ + 1];
+ char filestr[ROSH_PATH_SZ];
char buf[ROSH_BUF_SZ];
int numrd;
int cmdpos;
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
/* Initialization */
filestr[0] = 0;
cmdpos = 0;
@@ -306,6 +307,7 @@ void rosh_cat(const char *cmdstr, const char *pwdstr)
fclose(f);
} else {
rosh_error(errno, "cat", filestr);
+ errno = 0;
}
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
}
@@ -313,15 +315,14 @@ void rosh_cat(const char *cmdstr, const char *pwdstr)
/* Change PWD (Present Working Directory)
* cmdstr command string to process
- * pwdstr Present Working Directory string
* ipwdstr Initial PWD
*/
-void rosh_cd(const char *cmdstr, char *pwdstr, const char *ipwdstr)
+void rosh_cd(const char *cmdstr, const char *ipwdstr)
{
int rv;
- char filestr[ROSH_PATH_SZ + 1];
+ char filestr[ROSH_PATH_SZ];
int cmdpos;
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
/* Initialization */
filestr[0] = 0;
cmdpos = 0;
@@ -329,186 +330,456 @@ void rosh_cd(const char *cmdstr, char *pwdstr, const char *ipwdstr)
/* skip the first word */
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
- ROSH_COM32
- (" -- cd (Change Directory) not implemented for use with run and exit.\n");
if (strlen(filestr) != 0)
rv = chdir(filestr);
else
rv = chdir(ipwdstr);
if (rv != 0) {
rosh_error(errno, "cd", filestr);
+ errno = 0;
} else {
- getcwd(pwdstr, ROSH_PATH_SZ + 1);
- printf(" %s\n", pwdstr);
+#ifdef DO_DEBUG
+ if (getcwd(filestr, ROSH_PATH_SZ))
+ ROSH_DEBUG(" %s\n", filestr);
+#endif /* DO_DEBUG */
}
} /* rosh_cd */
/* Print the syslinux config file name
- * cmdstr command string to process
- * pwdstr Present Working Directory string
*/
-void rosh_cfg(const char *cmdstr, const char *pwdstr)
+void rosh_cfg(void)
{
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
printf("CFG: '%s'\n", syslinux_config_file());
} /* rosh_cfg */
+/* Process optstr to optarr
+ * optstr option string to process
+ * optarr option array to populate
+ */
+void rosh_ls_arg_opt(const char *optstr, int *optarr)
+{
+ char *cpos;
+ cpos = strchr(optstr, 'l');
+ if (cpos) {
+ optarr[0] = cpos - optstr;
+ } else {
+ optarr[0] = -1;
+ }
+ cpos = strchr(optstr, 'F');
+ if (cpos) {
+ optarr[1] = cpos - optstr;
+ } else {
+ optarr[1] = -1;
+ }
+ cpos = strchr(optstr, 'i');
+ if (cpos) {
+ optarr[2] = cpos - optstr;
+ } else {
+ optarr[2] = -1;
+ }
+} /* rosh_ls_arg_opt */
+
+/* Retrieve the size of a file argument
+ * filestr directory name of directory entry
+ * de directory entry
+ */
+int rosh_ls_de_size(const char *filestr, struct dirent *de)
+{
+ int de_size;
+ char filestr2[ROSH_PATH_SZ];
+ int fd2, file2pos;
+ struct stat fdstat;
+ int status;
+
+ filestr2[0] = 0;
+ file2pos = -1;
+ if (filestr) {
+ file2pos = strlen(filestr);
+ memcpy(filestr2, filestr, file2pos);
+ filestr2[file2pos] = '/';
+ }
+ strcpy(filestr2 + file2pos + 1, de->d_name);
+ fd2 = open(filestr2, O_RDONLY);
+ status = fstat(fd2, &fdstat);
+ fd2 = close(fd2);
+ de_size = (int)fdstat.st_size;
+ return de_size;
+} /* rosh_ls_de_size */
+
+/* Retrieve the size and mode of a file
+ * filestr directory name of directory entry
+ * de directory entry
+ */
+int rosh_ls_de_size_mode(struct dirent *de, mode_t * st_mode)
+{
+ int de_size;
+// char filestr2[ROSH_PATH_SZ];
+// int file2pos;
+ struct stat fdstat;
+ int status;
+
+/* filestr2[0] = 0;
+ file2pos = -1;*/
+ fdstat.st_size = 0;
+ fdstat.st_mode = 0;
+/* if (filestr) {
+ file2pos = strlen(filestr);
+ memcpy(filestr2, filestr, file2pos);
+ filestr2[file2pos] = '/';
+ }
+ strcpy(filestr2 + file2pos + 1, de->d_name);*/
+ status = stat(de->d_name, &fdstat);
+ ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno);
+ if (errno) {
+ rosh_error(errno, "ls:szmd.stat", de->d_name);
+ errno = 0;
+ }
+ de_size = (int)fdstat.st_size;
+ *st_mode = fdstat.st_mode;
+ return de_size;
+} /* rosh_ls_de_size_mode */
+
+/* Returns the Inode number if fdstat contains it
+ * fdstat struct to extract inode from if not COM32, for now
+ */
+long rosh_ls_d_ino(struct stat *fdstat)
+{
+ long de_ino;
+#ifdef __COM32__
+ if (fdstat)
+ de_ino = -1;
+ else
+ de_ino = 0;
+#else /* __COM32__ */
+ de_ino = fdstat->st_ino;
+#endif /* __COM32__ */
+ return de_ino;
+}
+
+/* Convert a d_type to a single char in human readable format
+ * d_type d_type to convert
+ * returns human readable single character; a space if other
+ */
+char rosh_d_type2char_human(unsigned char d_type)
+{
+ char ret;
+ switch (d_type) {
+ case DT_UNKNOWN:
+ ret = 'U';
+ break; /* Unknown */
+ case DT_FIFO:
+ ret = 'F';
+ break; /* FIFO */
+ case DT_CHR:
+ ret = 'C';
+ break; /* Char Dev */
+ case DT_DIR:
+ ret = 'D';
+ break; /* Directory */
+ case DT_BLK:
+ ret = 'B';
+ break; /* Block Dev */
+ case DT_REG:
+ ret = 'R';
+ break; /* Regular File */
+ case DT_LNK:
+ ret = 'L';
+ break; /* Link, Symbolic */
+ case DT_SOCK:
+ ret = 'S';
+ break; /* Socket */
+ case DT_WHT:
+ ret = 'W';
+ break; /* UnionFS Whiteout */
+ default:
+ ret = ' ';
+ }
+ return ret;
+} /* rosh_d_type2char_human */
+
+/* Convert a d_type to a single char by ls's prefix standards for -l
+ * d_type d_type to convert
+ * returns ls style single character; a space if other
+ */
+char rosh_d_type2char_lspre(unsigned char d_type)
+{
+ char ret;
+ switch (d_type) {
+ case DT_FIFO:
+ ret = 'p';
+ break;
+ case DT_CHR:
+ ret = 'c';
+ break;
+ case DT_DIR:
+ ret = 'd';
+ break;
+ case DT_BLK:
+ ret = 'b';
+ break;
+ case DT_REG:
+ ret = '-';
+ break;
+ case DT_LNK:
+ ret = 'l';
+ break;
+ case DT_SOCK:
+ ret = 's';
+ break;
+ default:
+ ret = '?';
+ }
+ return ret;
+} /* rosh_d_type2char_lspre */
+
+/* Convert a d_type to a single char by ls's classify (-F) suffix standards
+ * d_type d_type to convert
+ * returns ls style single character; a space if other
+ */
+char rosh_d_type2char_lssuf(unsigned char d_type)
+{
+ char ret;
+ switch (d_type) {
+ case DT_FIFO:
+ ret = '|';
+ break;
+ case DT_DIR:
+ ret = '/';
+ break;
+ case DT_LNK:
+ ret = '@';
+ break;
+ case DT_SOCK:
+ ret = '=';
+ break;
+ default:
+ ret = ' ';
+ }
+ return ret;
+} /* rosh_d_type2char_lssuf */
+
+/* Converts data in the "other" place of st_mode to a ls-style string
+ * st_mode Mode in other to analyze
+ * st_mode_str string to hold converted string
+ */
+void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str)
+{
+ st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-');
+ st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-');
+ st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-');
+}
+
+/* Converts st_mode to an ls-style string
+ * st_mode mode to convert
+ * st_mode_str string to hold converted string
+ */
+void rosh_st_mode2str(mode_t st_mode, char *st_mode_str)
+{
+ st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode));
+ rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1);
+ rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4);
+ rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7);
+ st_mode_str[10] = 0;
+} /* rosh_st_mode2str */
+
+/* Output a single entry
+ * filestr directory name to list
+ * de directory entry
+ * optarr Array of options
+ */
+void rosh_ls_arg_dir_de(struct dirent *de, const int *optarr)
+{
+ int de_size;
+ mode_t st_mode;
+ char st_mode_str[11];
+ st_mode = 0;
+ if (optarr[2] > -1)
+ printf("%10d ", (int)de->d_ino);
+ if (optarr[0] > -1) {
+ de_size = rosh_ls_de_size_mode(de, &st_mode);
+ rosh_st_mode2str(st_mode, st_mode_str);
+ ROSH_DEBUG2("%04X ", st_mode);
+ printf("%s %10d ", st_mode_str, de_size);
+ }
+ ROSH_DEBUG("'");
+ printf("%s", de->d_name);
+ ROSH_DEBUG("'");
+ if (optarr[1] > -1)
+ printf("%c", rosh_d_type2char_lssuf(de->d_type));
+ printf("\n");
+} /* rosh_ls_arg_dir_de */
+
+/* Output listing of a regular directory
+ * filestr directory name to list
+ * d the open DIR
+ * optarr Array of options
+ NOTE:This is where I could use qsort
+ */
+void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr)
+{
+ struct dirent *de;
+ int filepos;
+
+ filepos = 0;
+ while ((de = readdir(d))) {
+ filepos++;
+ rosh_ls_arg_dir_de(de, optarr);
+ }
+ if (errno)
+ rosh_error(errno, "ls:arg_dir", filestr);
+ else if (filepos == 0)
+ ROSH_DEBUG("0 files found");
+} /* rosh_ls_arg_dir */
+
/* Simple directory listing for one argument (file/directory) based on
* filestr and pwdstr
* ifilstr input filename/directory name to list
* pwdstr Present Working Directory string
+ * optarr Option Array
*/
-void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
+void rosh_ls_arg(const char *filestr, const int *optarr)
{
struct stat fdstat;
int status;
- int fd;
- char filestr[ROSH_PATH_SZ + 1];
- int filepos;
+// char filestr[ROSH_PATH_SZ];
+// int filepos;
DIR *d;
- struct dirent *de;
-#ifdef DO_DEBUG
- char filestr2[ROSH_PATH_SZ + 1];
- int fd2, file2pos;
-#ifdef __COM32__
-// int inchar;
- char ty;
-#endif /* __COM32__ */
-#endif /* DO_DEBUG */
+ struct dirent de;
/* Initialization; make filestr based on leading character of ifilstr
and pwdstr */
- if (ifilstr[0] == SEP) {
- strcpy(filestr, ifilstr);
- } else {
- strcpy(filestr, pwdstr);
- filepos = strlen(pwdstr);
- if (filestr[filepos - 1] != SEP)
- filestr[filepos++] = SEP;
- strcpy(filestr + filepos, ifilstr);
- ROSH_DEBUG("--'%s'\n", filestr);
- }
- fd = open(filestr, O_RDONLY);
- if (fd == -1) {
- status = fstat(fd, &fdstat);
- if (S_ISDIR(fdstat.st_mode)) {
- ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr);
- d = fdopendir(fd);
- de = readdir(d);
- while (de != NULL) {
-#ifdef DO_DEBUG
- filestr2[0] = 0;
- file2pos = strlen(filestr);
- memcpy(filestr2, filestr, file2pos);
- filestr2[file2pos] = '/';
- strcpy(filestr2 + file2pos + 1, de->d_name);
- fd2 = open(filestr2, O_RDONLY);
- status = fstat(fd2, &fdstat);
- printf("@%8d:%8d:", (int)de->d_ino, (int)fdstat.st_size);
- fd2 = close(fd2);
-#endif /* DO_DEBUG */
- printf("%s\n", de->d_name);
-#ifdef DO_DEBUG
-// inchar = fgetc(stdin);
-#endif /* DO_DEBUG */
- de = readdir(d);
- }
+// rosh_qualify_filestr(filestr, ifilstr, pwdstr);
+ fdstat.st_mode = 0;
+ fdstat.st_size = 0;
+ ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1],
+ optarr[2]);
+
+ /* Now, the real work */
+ errno = 0;
+ status = stat(filestr, &fdstat);
+ if (status == 0) {
+ if (S_ISDIR(fdstat.st_mode)) {
+ ROSH_DEBUG("PATH '%s' is a directory\n", filestr);
+ d = opendir(filestr);
+ rosh_ls_arg_dir(filestr, d, optarr);
closedir(d);
- } else if (S_ISREG(fdstat.st_mode)) {
- ROSH_DEBUG("PATH '%s' is a regular file\n", ifilstr);
- printf("%8d:%s\n", (int)fdstat.st_size, ifilstr);
} else {
- ROSH_DEBUG("PATH '%s' is some other file\n", ifilstr);
- printf(" :%s\n", ifilstr);
- }
- } else {
-#ifdef __COM32__
- if (filestr[strlen(filestr) - 1] == SEP) {
- /* Directory */
- filepos = 0;
- d = opendir(filestr);
- if (d != NULL) {
- //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset);
- de = readdir(d);
- while (de != NULL) {
- filepos++;
-#ifdef DO_DEBUG
-// if (strlen(de->d_name) > 25) de->d_name[25] = 0;
- switch (de->d_type) {
- case 16:
- ty = 'D';
- break;
- case 32:
- ty = 'F';
- break;
- default:
- ty = '*';
- }
-#endif /* DO_DEBUG */
-// printf("%s\n", de->d_name);
- printf("'%s'\n", de->d_name);
-#ifdef DO_DEBUG
-// inchar = fgetc(stdin);
-// fgets(instr, ROSH_CMD_SZ, stdin);
-#endif /* DO_DEBUG */
- de = readdir(d);
-// if(filepos>15){ de = NULL; printf("Force Break\n");}
- }
- closedir(d);
+ de.d_ino = rosh_ls_d_ino(&fdstat);
+ de.d_type = (IFTODT(fdstat.st_mode));
+ strcpy(de.d_name, filestr);
+ if (S_ISREG(fdstat.st_mode)) {
+ ROSH_DEBUG("PATH '%s' is a regular file\n", filestr);
} else {
- rosh_error(0, "dir:NULL", filestr);
+ ROSH_DEBUG("PATH '%s' is some other file\n", filestr);
}
- } else {
- rosh_error(errno, "dir_c32", filestr);
+ rosh_ls_arg_dir_de(&de, optarr);
+/* if (ifilstr[0] == SEP)
+ rosh_ls_arg_dir_de(NULL, &de, optarr);
+ else
+ rosh_ls_arg_dir_de(pwdstr, &de, optarr);*/
}
-#else
- rosh_error(errno, "dir", filestr);
-#endif /* __COM32__ */
+ } else {
+ rosh_error(errno, "ls", filestr);
+ errno = 0;
+ }
+ return;
+} /* rosh_ls_arg */
+
+/* Parse options that may be present in the cmdstr
+ * filestr Possible option string to parse
+ * optstr Current options
+ * returns 1 if filestr does not begin with '-' else 0
+ */
+int rosh_ls_parse_opt(const char *filestr, char *optstr)
+{
+ int ret;
+ if (filestr[0] == '-') {
+ ret = 0;
+ if (optstr)
+ strcat(optstr, filestr + 1);
+ } else {
+ ret = 1;
}
-} /* rosh_dir_arg */
+ ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr,
+ ret);
+ return ret;
+} /* rosh_ls_parse_opt */
-/* Simple directory listing based on cmdstr and pwdstr
+/* List Directory based on cmdstr and pwdstr
* cmdstr command string to process
* pwdstr Present Working Directory string
*/
-void rosh_dir(const char *cmdstr, const char *pwdstr)
+void rosh_ls(const char *cmdstr)
{
- char filestr[ROSH_PATH_SZ + 1];
- int cmdpos; /* Position within cmdstr */
+ char filestr[ROSH_PATH_SZ];
+ char optstr[ROSH_OPT_SZ]; /* Options string */
+ int cmdpos, tpos; /* Position within cmdstr, temp position */
+ int numargs; /* number of non-option arguments */
+ int argpos; /* number of non-option arguments processed */
+ int optarr[3];
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
/* Initialization */
filestr[0] = 0;
+ optstr[0] = 0;
cmdpos = 0;
+ numargs = 0;
+ argpos = 0;
/* skip the first word */
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
- cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
+ tpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
/* If there are no real arguments, substitute PWD */
- if (strlen(filestr) == 0)
- strcpy(filestr, pwdstr);
+ if (strlen(filestr) == 0) {
+ strcpy(filestr, ".");
+ cmdpos = tpos;
+ } else { /* Parse for command line options */
+ while (strlen(filestr) > 0) {
+ numargs += rosh_ls_parse_opt(filestr, optstr);
+ tpos = rosh_parse_sp_1(filestr, cmdstr, tpos);
+ }
+ if (numargs == 0) {
+ strcpy(filestr, ".");
+ cmdpos = tpos;
+ } else {
+ cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
+ }
+ }
+#ifdef DO_DEBUG
+ if (!strchr(optstr, 'l'))
+ strcat(optstr, "l");
+#endif /* DO_DEBUG */
+ rosh_ls_arg_opt(optstr, optarr);
+ ROSH_DEBUG("\tfopt: '%s'\n", optstr);
while (strlen(filestr) > 0) {
- rosh_dir_arg(filestr, pwdstr);
- cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
+ if (rosh_ls_parse_opt(filestr, NULL)) {
+ rosh_ls_arg(filestr, optarr);
+ argpos++;
+ }
+ if (argpos < numargs)
+ cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
+ else
+ break;
}
-} /* rosh_dir */
+} /* rosh_ls */
-/* List Directory; Calls rosh_dir() for now.
+/* Simple directory listing; calls rosh_ls()
* cmdstr command string to process
* pwdstr Present Working Directory string
*/
-void rosh_ls(const char *cmdstr, const char *pwdstr)
+void rosh_dir(const char *cmdstr)
{
- printf(" ls implemented as dir (for now)\n");
- rosh_dir(cmdstr, pwdstr);
-} /* rosh_ls */
+ ROSH_DEBUG(" dir implemented as ls\n");
+ rosh_ls(cmdstr);
+} /* rosh_dir */
/* Page through a buffer string
* buf Buffer to page through
*/
+//HERE: minor pagination issue; sometimes prints 1 less than rows
void rosh_more_buf(char *buf, int buflen, int rows, int cols)
{
- char *bufp, *bufeol; /* Pointer to current and next end-of-line
- position in buffer */
+ char *bufp, *bufeol, *bufeol2; /* Pointer to current and next
+ end-of-line position in buffer */
int bufpos, bufcnt; /* current position, count characters */
char scrbuf[ROSH_SBUF_SZ];
int inc;
@@ -520,23 +791,17 @@ void rosh_more_buf(char *buf, int buflen, int rows, int cols)
bufp = buf + bufpos;
bufeol = bufp;
numln = rows - 1;
- printf("--(%d)\n", buflen);
-// printf("--termIOS CONSTS: ");
-// printf("ISIG=%08X ", ISIG);
-// printf("ICANON=%08X ", ICANON);
-// printf("ECHO=%08X ", ECHO);
-// printf("=%08X", );
-// printf("\n");
+ ROSH_DEBUG("--(%d)\n", buflen);
while (bufpos < buflen) {
for (i = 0; i < numln; i++) {
- bufeol = strchr(bufeol, '\n');
- if (bufeol == NULL) {
+ bufeol2 = strchr(bufeol, '\n');
+ if (bufeol2 == NULL) {
bufeol = buf + buflen;
i = numln;
} else {
- bufeol++;
+ i += ((bufeol2 - bufeol) / cols);
+ bufeol = bufeol2 + 1;
}
-// printf("--readln\n");
}
bufcnt = bufeol - bufp;
printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos);
@@ -557,12 +822,8 @@ void rosh_more_buf(char *buf, int buflen, int rows, int cols)
break;
case ' ':
numln = rows - 1;
-// default:
}
}
-/*tcgetattr(0, &tio);
-rosh_print_tc(&tio);
-printf("\n--END\n");*/
} /* rosh_more_buf */
/* Page through a single file using the open file stream
@@ -599,18 +860,16 @@ void rosh_more_fd(int fd, int rows, int cols)
/* Page through a file like the more command
* cmdstr command string to process
- * pwdstr Present Working Directory string
* ipwdstr Initial PWD
*/
-void rosh_more(const char *cmdstr, const char *pwdstr)
- /*, const char *ipwdstr) */
+void rosh_more(const char *cmdstr)
{
int fd;
- char filestr[ROSH_PATH_SZ + 1];
+ char filestr[ROSH_PATH_SZ];
int cmdpos;
int rows, cols;
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
/* Initialization */
filestr[0] = 0;
cmdpos = 0;
@@ -623,7 +882,7 @@ void rosh_more(const char *cmdstr, const char *pwdstr)
if (!cols)
cols = 75;
}
- ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols);
+ ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols);
/* skip the first word */
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
@@ -640,6 +899,7 @@ void rosh_more(const char *cmdstr, const char *pwdstr)
close(fd);
} else {
rosh_error(errno, "more", filestr);
+ errno = 0;
}
cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos);
}
@@ -652,119 +912,149 @@ void rosh_more(const char *cmdstr, const char *pwdstr)
* pwdstr Present Working Directory string
* ipwdstr Initial PWD
*/
-void rosh_less(const char *cmdstr, const char *pwdstr)
+void rosh_less(const char *cmdstr)
{
printf(" less implemented as more (for now)\n");
- rosh_more(cmdstr, pwdstr);
+ rosh_more(cmdstr);
} /* rosh_less */
/* Show PWD
* cmdstr command string to process
- * pwdstr Present Working Directory string
*/
-void rosh_pwd(const char *cmdstr, const char *pwdstr)
+void rosh_pwd(const char *cmdstr)
{
int istr;
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
- printf("%s\n", pwdstr);
+ char pwdstr[ROSH_PATH_SZ];
+ if (cmdstr)
+ istr = 0;
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
+ errno = 0;
+ if (getcwd(pwdstr, ROSH_PATH_SZ)) {
+ printf("%s\n", pwdstr);
+ } else {
+ rosh_error(errno, "pwd", "");
+ errno = 0;
+ }
istr = htonl(*(int *)pwdstr);
- ROSH_DEBUG(" --%08X\n", istr);
+ ROSH_DEBUG2(" --%08X\n", istr);
} /* rosh_pwd */
+/* Reboot
+ */
+void rosh_reboot(void)
+{
+// char cmdstr[ROSH_CMD_SZ];
+// printf
+ syslinux_reboot(0);
+} /* rosh_reboot */
+
/* Run a boot string, calling syslinux_run_command
* cmdstr command string to process
- * pwdstr Present Working Directory string
- * ipwdstr Initial PWD
*/
-void rosh_run(const char *cmdstr, const char *pwdstr, const char *ipwdstr)
+void rosh_run(const char *cmdstr)
{
int cmdpos;
char *cmdptr;
- char istr[ROSH_CMD_SZ]; /* input command string */
cmdpos = 0;
- ROSH_DEBUG("CMD: '%s'\npwd: '%s'\n", cmdstr, pwdstr);
+ ROSH_DEBUG("CMD: '%s'\n", cmdstr);
/* skip the first word */
cmdpos = rosh_search_sp(cmdstr, cmdpos);
/* skip spaces */
cmdpos = rosh_search_nonsp(cmdstr, cmdpos);
cmdptr = (char *)(cmdstr + cmdpos);
printf("--run: '%s'\n", cmdptr);
- /* //HERE--Reparse if pwdstr != ipwdstr; seems a little daunting as
- detecting params vs filenames is difficult/impossible */
- if (strcmp(pwdstr, ipwdstr) != 0) {
- /* For now, just prompt for verification */
- printf(" from directory '%s'? (y/N):", pwdstr);
- fgets(istr, ROSH_CMD_SZ, stdin);
- if ((istr[0] != 'y') && (istr[0] != 'Y')) {
- printf("Aborting run\n");
- return;
- }
- printf("Run anyways\n");
- }
syslinux_run_command(cmdptr);
} /* rosh_run */
/* Process a single command string and call handling function
* cmdstr command string to process
- * pwdstr Present Working Directory string
* ipwdstr Initial Present Working Directory string
* returns Whether to exit prompt
*/
-char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr)
+char rosh_command(const char *cmdstr, const char *ipwdstr)
{
char do_exit;
+ char tstr[ROSH_CMD_SZ];
+ int tlen;
do_exit = false;
ROSH_DEBUG("--cmd:'%s'\n", cmdstr);
+ tlen = rosh_parse_sp_1(tstr, cmdstr, 0);
switch (cmdstr[0]) {
case 'e':
case 'E':
case 'q':
case 'Q':
- do_exit = true;
+ if ((strncasecmp("exit", tstr, tlen) == 0) ||
+ (strncasecmp("quit", tstr, tlen) == 0))
+ do_exit = true;
+ else
+ rosh_help(1, NULL);
break;
case 'c':
case 'C': /* run 'cd' 'cat' 'cfg' */
switch (cmdstr[1]) {
case 'a':
case 'A':
- rosh_cat(cmdstr, pwdstr);
+ if (strncasecmp("cat", tstr, tlen) == 0)
+ rosh_cat(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'd':
case 'D':
- rosh_cd(cmdstr, pwdstr, ipwdstr);
+ if (strncasecmp("cd", tstr, tlen) == 0)
+ rosh_cd(cmdstr, ipwdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'f':
case 'F':
- rosh_cfg(cmdstr, pwdstr);
+ if (strncasecmp("cfg", tstr, tlen) == 0)
+ rosh_cfg();
+ else
+ rosh_help(1, NULL);
break;
default:
- rosh_help(1);
+ rosh_help(1, NULL);
}
break;
case 'd':
case 'D': /* run 'dir' */
- rosh_dir(cmdstr, pwdstr);
+ if (strncasecmp("dir", tstr, tlen) == 0)
+ rosh_dir(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'h':
case 'H':
case '?':
- rosh_help(2);
+ if ((strncasecmp("help", tstr, tlen) == 0) || (tlen == 1))
+ rosh_help(2, cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'l':
case 'L': /* run 'ls' 'less' */
switch (cmdstr[1]) {
case 0:
+ case ' ':
case 's':
case 'S':
- rosh_ls(cmdstr, pwdstr);
+ if (strncasecmp("ls", tstr, tlen) == 0)
+ rosh_ls(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'e':
case 'E':
- rosh_less(cmdstr, pwdstr);
+ if (strncasecmp("less", tstr, tlen) == 0)
+ rosh_less(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
default:
- rosh_help(1);
+ rosh_help(1, NULL);
}
break;
case 'm':
@@ -772,33 +1062,62 @@ char rosh_command(const char *cmdstr, char *pwdstr, const char *ipwdstr)
switch (cmdstr[1]) {
case 'a':
case 'A':
- rosh_help(2);
+ if (strncasecmp("man", tstr, tlen) == 0)
+ rosh_help(2, cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'o':
case 'O':
- rosh_more(cmdstr, pwdstr);
+ if (strncasecmp("more", tstr, tlen) == 0)
+ rosh_more(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
default:
- rosh_help(1);
+ rosh_help(1, NULL);
}
break;
case 'p':
case 'P': /* run 'pwd' */
- rosh_pwd(cmdstr, pwdstr);
+ if (strncasecmp("pwd", tstr, tlen) == 0)
+ rosh_pwd(cmdstr);
+ else
+ rosh_help(1, NULL);
break;
case 'r':
case 'R': /* run 'run' */
- rosh_run(cmdstr, pwdstr, ipwdstr);
+ switch (cmdstr[1]) {
+ case 0:
+ case ' ':
+ case 'e':
+ case 'E':
+ if (strncasecmp("reboot", tstr, tlen) == 0)
+ rosh_reboot();
+ else
+ rosh_help(1, NULL);
+ break;
+ case 'u':
+ case 'U':
+ if (strncasecmp("run", tstr, tlen) == 0)
+ rosh_run(cmdstr);
+ else
+ rosh_help(1, NULL);
+ break;
+ }
break;
case 'v':
case 'V':
- rosh_version();
+ if (strncasecmp("version", tstr, tlen) == 0)
+ rosh_version();
+ else
+ rosh_help(1, NULL);
break;
case 0:
case '\n':
break;
default:
- rosh_help(1);
+ rosh_help(1, NULL);
} /* switch(cmdstr[0]) */
return do_exit;
} /* rosh_command */
@@ -812,33 +1131,28 @@ int rosh_prompt(const char *icmdstr)
{
int rv;
char cmdstr[ROSH_CMD_SZ];
- char pwdstr[ROSH_PATH_SZ + 1], ipwdstr[ROSH_PATH_SZ + 1];
-/* int numchar;
-*/ char do_exit;
+ char ipwdstr[ROSH_PATH_SZ];
+ char do_exit;
char *c;
rv = 0;
do_exit = false;
- strcpy(pwdstr, "/");
- getcwd(pwdstr, ROSH_PATH_SZ + 1);
- strcpy(ipwdstr, pwdstr); /* Retain the original PWD */
+ if (!getcwd(ipwdstr, ROSH_PATH_SZ))
+ strcpy(ipwdstr, "./");
if (icmdstr[0] != '\0')
- do_exit = rosh_command(icmdstr, pwdstr, ipwdstr);
+ do_exit = rosh_command(icmdstr, ipwdstr);
while (!(do_exit)) {
- console_ansi_std();
+ /* Extra preceeding newline */
printf("\nrosh: ");
/* Read a line from console */
- fgets(cmdstr, ROSH_CMD_SZ, stdin);
- /* remove newline from input string */
- c = strchr(cmdstr, '\n');
- *c = 0;
- do_exit = rosh_command(cmdstr, pwdstr, ipwdstr);
- }
- if (strcmp(pwdstr, ipwdstr) != 0) {
- /* Change directory to the original directory */
- strcpy(cmdstr, "cd ");
- strcpy(cmdstr + 3, ipwdstr);
- rosh_cd(cmdstr, pwdstr, ipwdstr);
+ if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) {
+ /* remove newline from input string */
+ c = strchr(cmdstr, '\n');
+ *c = 0;
+ do_exit = rosh_command(cmdstr, ipwdstr);
+ } else {
+ do_exit = false;
+ }
}
return rv;
}
@@ -850,16 +1164,15 @@ int main(int argc, char *argv[])
/* Initialization */
rv = 0;
- console_ansi_std();
-// console_ansi_raw();
+ rosh_console_std();
if (argc != 1) {
rv = rosh_argcat(cmdstr, argc, argv, 1);
} else {
rosh_version();
+ print_beta();
cmdstr[0] = '\0';
}
rv = rosh_prompt(cmdstr);
printf("--Exiting '%s'\n", APP_NAME);
- console_ansi_std();
return rv;
}
diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h
index 0c41bac..a8edda6 100644
--- a/com32/rosh/rosh.h
+++ b/com32/rosh/rosh.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 2008 Gene Cumm - All Rights Reserved
+ * Copyright 2008-2009 Gene Cumm - All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
/*
* History
+ * b034 Improve debug functions to simpler code
* b021 Move much PreProcessing stuff to rosh.h
* b018 Create rosh_debug() macro
* b012 Version of rosh.c at time of creating this file.
@@ -37,28 +38,23 @@
#include <unistd.h> /* getcwd() */
#include <errno.h> /* errno; error macros */
#include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */
+#include <ctype.h> /* isspace() */
#include <getkey.h>
#include <consoles.h>
-/* A GNUC extension to void out unused functions are used */
-/* Plus, there seem to be other references for SYSLINUX to __GNUC__ */
-#ifndef __GNUC__
-#error SYSLINUX (I believe) requires __GNUC__
-#endif /* __GNUC__ */
-
-#define DO_DEBUG 1
-
#ifdef DO_DEBUG
-#define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__)
-#ifdef DO_DEBUG2
-#define ROSH_DEBUG2(f, ...) printf (f, ## __VA_ARGS__)
-#else /* DO_DEBUG2 */
-#define ROSH_DEBUG2(f, ...) ((void)0)
-#endif /* DO_DEBUG2 */
+# define ROSH_DEBUG printf
+/* define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) */
+# ifdef DO_DEBUG2
+# define ROSH_DEBUG2 printf
+# else /* DO_DEBUG2 */
+ /* This forces a format argument into the function call */
+# define ROSH_DEBUG2(f, ...) ((void)0)
+# endif /* DO_DEBUG2 */
#else /* DO_DEBUG */
-#define ROSH_DEBUG(f, ...) ((void)0)
-#define ROSH_DEBUG2(f, ...) ((void)0)
+# define ROSH_DEBUG(f, ...) ((void)0)
+# define ROSH_DEBUG2(f, ...) ((void)0)
#endif /* DO_DEBUG */
#ifdef __COM32__
@@ -66,11 +62,38 @@
#include <console.h> /* openconsole() */
#include <syslinux/config.h> /* Has info on the SYSLINUX variant */
#include <syslinux/boot.h> /* syslinux_run_command() */
+#include <syslinux/reboot.h>
#define ROSH_COM32(f, ...) printf (f, ## __VA_ARGS__)
+#define rosh_console_std() console_ansi_std()
+#define rosh_console_raw() console_ansi_raw()
+
+int stat(const char *pathname, struct stat *buf)
+{
+ int fd, status, ret = -1;
+ DIR *d;
+
+ d = opendir(pathname);
+ if (d != NULL) {
+ closedir(d);
+ ret = 0;
+ buf->st_mode = S_IFDIR | 0555;
+ buf->st_size = 0;
+ } else if ((errno == 0) || (errno == ENOENT) || (errno == ENOTDIR)) {
+ fd = open(pathname, O_RDONLY);
+ if (fd != 1) {
+ status = fstat(fd, buf);
+ close(fd);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
#else
-#include <termios.h>
-#define ROSH_IS_COM32 0
-static inline char *syslinux_config_file()
+# include <termios.h>
+# define ROSH_IS_COM32 0
+
+static inline char *syslinux_config_file(void)
{
return "";
}
@@ -81,16 +104,16 @@ static inline int getscreensize(int fd, int *rows, int *cols)
int rv;
*rows = 0;
*cols = 0;
- if (rows) {
- str = getenv("LINES");
- if (str) {
- *rows = atoi(str);
+ if (fd == 1) {
+ if (rows) {
+ str = getenv("LINES");
+ if (str)
+ *rows = atoi(str);
}
- }
- if (cols) {
- str = getenv("COLUMNS");
- if (str) {
- *cols = atoi(str);
+ if (cols) {
+ str = getenv("COLUMNS");
+ if (str)
+ *cols = atoi(str);
}
}
if (!rows || !cols)
@@ -102,6 +125,41 @@ static inline int getscreensize(int fd, int *rows, int *cols)
return rv;
}
+/*
+ * Switches console over to raw input mode. Allows get_key to get just
+ * 1 key sequence (without delay or display)
+ */
+void rosh_console_raw(void)
+{
+ struct termios tio;
+
+ console_ansi_raw(); /* Allows get_key to get just 1 key sequence
+ (w/o delay or display */
+ /* Deal with the changes that haven't been replicated to ansiraw.c */
+ tcgetattr(0, &tio);
+ tio.c_iflag &= ~IGNCR;
+ tcsetattr(0, TCSAFLUSH, &tio);
+}
+
+/*
+ * Switches back to standard getline mode.
+ */
+void rosh_console_std(void)
+{
+ struct termios tio;
+
+ console_ansi_std();
+ tcgetattr(0, &tio);
+ tio.c_iflag |= ICRNL;
+ tio.c_iflag &= ~IGNCR;
+ tcsetattr(0, TCSANOW, &tio);
+}
+
+void syslinux_reboot(int warm)
+{
+ printf("Test Reboot(%d)\n", warm);
+}
+
#define ROSH_COM32(f, ...) ((void)0)
#define syslinux_run_command(f) ((void)0)
#endif /* __COM32__ */
@@ -110,43 +168,61 @@ static inline int getscreensize(int fd, int *rows, int *cols)
/* Size of buffer string */
#define ROSH_BUF_SZ 16384
-/* Size of screen output buffer (80*40) */
-#define ROSH_SBUF_SZ 1200
+/* Size of screen output buffer (80*40) //HERE */
+#define ROSH_SBUF_SZ ((80 + 2) * 40)
/* Size of command buffer string */
#ifdef MAX_CMDLINE_LEN
-#define ROSH_CMD_SZ MAX_CMDLINE_LEN
-#else
-#ifdef COMMAND_LINE_SIZE
-#define ROSH_CMD_SZ COMMAND_LINE_SIZE
+# define ROSH_CMD_SZ MAX_CMDLINE_LEN
+#elif COMMAND_LINE_SIZE
+# define ROSH_CMD_SZ COMMAND_LINE_SIZE
#else
-#define ROSH_CMD_SZ 2048
-#endif /* COMMAND_LINE_SIZE */
+# define ROSH_CMD_SZ_LG2 12
+# define ROSH_CMD_SZ (1 << ROSH_CMD_SZ_LG2)
#endif /* MAX_CMDLINE_LEN */
/* Size of path buffer string */
#ifdef PATH_MAX
-#define ROSH_PATH_SZ PATH_MAX
+# define ROSH_PATH_SZ PATH_MAX
#elif NAME_MAX
-#define ROSH_PATH_SZ NAME_MAX
+# define ROSH_PATH_SZ NAME_MAX
+#elif FILENAME_MAX
+# define ROSH_PATH_SZ FILENAME_MAX
#else
-#define ROSH_PATH_SZ 255
-#endif /* NAME_MAX */
+# define ROSH_PATH_SZ_LG2 8
+# define ROSH_PATH_SZ (1 << ROSH_PATH_SZ_LG2)
+#endif /* PATH_MAX */
+
+#define ROSH_OPT_SZ 8
+
+const char rosh_beta_str[] =
+ " ROSH is currently beta. Constructive feedback is appreciated";
+
+const char rosh_cd_norun_str[] =
+ " -- cd (Change Directory) not implemented for use with run and exit.\n";
+
+const char rosh_help_ls_str[] = "ls List contents of current directory\n\
+ -l Long format\n\
+ -i Inode; print Inode of file\n\
+ -F Classify; Add a 1-character suffix to classify files";
const char rosh_help_str1[] =
"Commands: ? cat cd cfg dir exit help less ls man more pwd run quit ver";
const char rosh_help_str2[] =
- "Commands: (some 1-letter abreviations also allowed)\n\
- h HELP\n ALSO ? help man\n\
+ "Commands: (short generally non-ambiguous abreviations are also allowed)\n\
+ h HELP\n ALSO ? help man\n ALSO help <command>\n\
cat Concatenate file to console\n cat <file>\n\
cd Change to directory <dir>\n cd <dir>\n\
less Page a file with rewind\n\
ls List contents of current directory\n ls <dir>\n\
- ALSO dir\n\
+ ALSO l dir\n\
more Page a file\n\
pwd display Present Working Directory\n\
run Run a program/kernel with options\n\
+ r Reboot (if COM32)\n Also reboot\n\
exit Exit to previous environment\n ALSO quit";
+const char rosh_help_str_adv[] = "No additional help available for '%s'";
+
#endif /* Not ROSH_H */
diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h
index 0926c8d..f2b3bc2 100644
--- a/com32/sysdump/backend.h
+++ b/com32/sysdump/backend.h
@@ -50,5 +50,6 @@ struct backend *get_backend(const char *name);
/* backends */
extern struct backend be_tftp;
extern struct backend be_ymodem;
+extern struct backend be_srec;
#endif /* BACKEND_H */
diff --git a/com32/sysdump/be_tftp.c b/com32/sysdump/be_tftp.c
index 07fdb08..36a91eb 100644
--- a/com32/sysdump/be_tftp.c
+++ b/com32/sysdump/be_tftp.c
@@ -3,6 +3,7 @@
*/
#include <string.h>
+#include <stdio.h>
#include <syslinux/pxe.h>
#include <syslinux/config.h>
#include <netinet/in.h>
@@ -21,23 +22,30 @@ enum tftp_opcode {
struct tftp_state {
uint32_t my_ip;
uint32_t srv_ip;
+ uint32_t srv_gw;
uint16_t my_port;
uint16_t srv_port;
uint16_t seq;
};
+#define RCV_BUF 2048
+
static int send_ack_packet(struct tftp_state *tftp,
const void *pkt, size_t len)
{
com32sys_t ireg, oreg;
- t_PXENV_UDP_WRITE *uw = __com32.cs_bounce;
- t_PXENV_UDP_READ *ur = __com32.cs_bounce;
+ t_PXENV_UDP_WRITE *uw;
+ t_PXENV_UDP_READ *ur;
clock_t start;
static const clock_t timeouts[] = {
2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31,
37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 0
};
const clock_t *timeout;
+ int err = -1;
+
+ uw = lmalloc(sizeof *uw + len);
+ ur = lmalloc(sizeof *ur + RCV_BUF);
memset(&ireg, 0, sizeof ireg);
ireg.eax.w[0] = 0x0009;
@@ -46,6 +54,7 @@ static int send_ack_packet(struct tftp_state *tftp,
memset(uw, 0, sizeof uw);
memcpy(uw+1, pkt, len);
uw->ip = tftp->srv_ip;
+ uw->gw = tftp->srv_gw;
uw->src_port = tftp->my_port;
uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69);
uw->buffer_size = len;
@@ -65,7 +74,7 @@ static int send_ack_packet(struct tftp_state *tftp,
ur->dest_ip = tftp->my_ip;
ur->s_port = tftp->srv_port;
ur->d_port = tftp->my_port;
- ur->buffer_size = __com32.cs_bounce_size - sizeof *ur;
+ ur->buffer_size = RCV_BUF;
ur->buffer = FAR_PTR(ur+1);
ireg.ebx.w[0] = PXENV_UDP_READ;
@@ -82,15 +91,20 @@ static int send_ack_packet(struct tftp_state *tftp,
if (ntohs(xb[0]) == TFTP_ACK &&
ntohs(xb[1]) == tftp->seq) {
tftp->srv_port = ur->s_port;
- return 0; /* All good! */
+ err = 0; /* All good! */
+ goto done;
} else if (ntohs(xb[1]) == TFTP_ERROR) {
- return -1; /* All bad! */
+ goto done;
}
}
} while ((clock_t)(times(NULL) - start) < *timeout);
}
- return -1; /* No success... */
+done:
+ lfree(ur);
+ lfree(uw);
+
+ return err;
}
static int be_tftp_write(struct backend *be)
@@ -107,10 +121,31 @@ static int be_tftp_write(struct backend *be)
tftp.my_ip = sdi->pxe.myip;
tftp.my_port = htons(local_port++);
- tftp.srv_ip = pxe_dns(be->argv[1]);
+ tftp.srv_gw = ((tftp.srv_ip ^ tftp.my_ip) & sdi->pxe.ipinfo->netmask)
+ ? sdi->pxe.ipinfo->gateway : 0;
tftp.srv_port = 0;
tftp.seq = 0;
+ if (be->argv[1]) {
+ tftp.srv_ip = pxe_dns(be->argv[1]);
+ if (!tftp.srv_ip) {
+ printf("\nUnable to resolve hostname: %s\n", be->argv[1]);
+ return -1;
+ }
+ } else {
+ tftp.srv_ip = sdi->pxe.ipinfo->serverip;
+ if (!tftp.srv_ip) {
+ printf("\nNo server IP address\n");
+ return -1;
+ }
+ }
+
+ printf("server %u.%u.%u.%u... ",
+ ((uint8_t *)&tftp.srv_ip)[0],
+ ((uint8_t *)&tftp.srv_ip)[1],
+ ((uint8_t *)&tftp.srv_ip)[2],
+ ((uint8_t *)&tftp.srv_ip)[3]);
+
buffer[0] = 0;
buffer[1] = TFTP_WRQ;
nlen = strlcpy(buffer+2, be->argv[0], 512);
@@ -137,7 +172,7 @@ static int be_tftp_write(struct backend *be)
struct backend be_tftp = {
.name = "tftp",
- .helpmsg = "filename tftp_server",
- .minargs = 2,
+ .helpmsg = "filename [tftp_server]",
+ .minargs = 1,
.write = be_tftp_write,
};
diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c
index d4a0320..d0d40a7 100644
--- a/com32/sysdump/main.c
+++ b/com32/sysdump/main.c
@@ -41,6 +41,7 @@ static void dump_all(struct backend *be, const char *argv[])
dump_memory_map(be);
dump_memory(be);
dump_dmi(be);
+ dump_acpi(be);
dump_cpuid(be);
dump_pci(be);
dump_vesa_tables(be);
@@ -53,6 +54,7 @@ static struct backend *backends[] =
{
&be_tftp,
&be_ymodem,
+ &be_srec,
NULL
};
diff --git a/com32/sysdump/memmap.c b/com32/sysdump/memmap.c
index a85f092..251107d 100644
--- a/com32/sysdump/memmap.c
+++ b/com32/sysdump/memmap.c
@@ -19,10 +19,12 @@ struct e820_info {
static void dump_e820(struct backend *be)
{
com32sys_t ireg, oreg;
- struct e820_info *curr = __com32.cs_bounce;
+ struct e820_info *curr;
struct e820_info *buf, *p;
int nentry, nalloc;
+ curr = lmalloc(sizeof *curr);
+
buf = p = NULL;
nentry = nalloc = 0;
memset(&ireg, 0, sizeof ireg);
@@ -56,7 +58,9 @@ static void dump_e820(struct backend *be)
if (nentry)
cpio_writefile(be, "memmap/15e820", buf, nentry*sizeof *buf);
+
free(buf);
+ lfree(curr);
}
void dump_memory_map(struct backend *be)
diff --git a/com32/sysdump/sysdump.h b/com32/sysdump/sysdump.h
index 61a04a2..a5b963f 100644
--- a/com32/sysdump/sysdump.h
+++ b/com32/sysdump/sysdump.h
@@ -7,6 +7,7 @@ void dump_memory_map(struct backend *);
void snapshot_lowmem(void);
void dump_memory(struct backend *);
void dump_dmi(struct backend *);
+void dump_acpi(struct backend *);
void dump_cpuid(struct backend *);
void dump_pci(struct backend *);
void dump_vesa_tables(struct backend *);
diff --git a/com32/sysdump/vesa.c b/com32/sysdump/vesa.c
index 9bdc715..017f9e4 100644
--- a/com32/sysdump/vesa.c
+++ b/com32/sysdump/vesa.c
@@ -7,6 +7,7 @@
void dump_vesa_tables(struct backend *be)
{
com32sys_t rm;
+ struct vesa_info *vip;
struct vesa_general_info *gip, gi;
struct vesa_mode_info *mip, mi;
uint16_t mode, *mode_ptr;
@@ -15,8 +16,9 @@ void dump_vesa_tables(struct backend *be)
printf("Scanning VESA BIOS... ");
/* Allocate space in the bounce buffer for these structures */
- gip = &((struct vesa_info *)__com32.cs_bounce)->gi;
- mip = &((struct vesa_info *)__com32.cs_bounce)->mi;
+ vip = lmalloc(sizeof *vip);
+ gip = &vip->gi;
+ mip = &vip->mi;
memset(&rm, 0, sizeof rm);
memset(gip, 0, sizeof *gip);
@@ -56,5 +58,6 @@ void dump_vesa_tables(struct backend *be)
cpio_writefile(be, modefile, &mi, sizeof mi);
}
+ lfree(vip);
printf("done.\n");
}
diff --git a/doc/comboot.txt b/doc/comboot.txt
index f39d724..4b4b880 100644
--- a/doc/comboot.txt
+++ b/doc/comboot.txt
@@ -426,8 +426,12 @@ AX=000Ah [2.00] Get Derivative-Specific Information
Output: AL 31h (SYSLINUX), 34h (EXTLINUX)
DL drive number
CL sector size as a power of 2 (9 = 512 bytes) [3.35]
+ CH mode [3.73]
+ 1 = CBIOS mode
+ 2 = EBIOS mode
ES:BX pointer to partition table entry (if DL >= 80h)
FS:SI pointer to initial ES:DI value [3.53]
+ GS:DI pointer to partition offset (QWORD) [4.00]
Note: This function was broken in EXTLINUX 3.00-3.02.
@@ -448,6 +452,7 @@ AX=000Ah [2.00] Get Derivative-Specific Information
ECX Local IP number (network byte order) [3.85]
ES:BX pointer to PXENV+ or !PXE structure
FS:SI pointer to original stack with invocation record
+ GS:DI pointer to network information [4.00]
Note: DX notes the API version detected by PXELINUX,
which may be more conservative than the actual version
@@ -481,6 +486,13 @@ AX=000Ah [2.00] Get Derivative-Specific Information
[fs:si+44] PXE return IP <- t.o.s. when PXELINUX invoked
[fs:si+46] PXE return CS
+ GS:DI points to a structure of the following form:
+
+ [gs:di+0] 4 - IPv4
+ [gs:di+4] My IP
+ [gs:di+8] Boot server IP
+ [gs:di+12] Gateway IP
+ [gs:di+16] Netmask
[ISOLINUX]
Input: AX 000Ah
@@ -493,6 +505,7 @@ AX=000Ah [2.00] Get Derivative-Specific Information
2 = Hybrid (hard disk), EBIOS mode
ES:BX pointer to El Torito spec packet
FS:SI pointer to initial ES:DI value [3.53]
+ GS:DI pointer to partition offset (QWORD) [4.00]
Note: Some very broken El Torito implementations do
not provide the spec packet information. If so, ES:BX
@@ -500,10 +513,6 @@ AX=000Ah [2.00] Get Derivative-Specific Information
AX=4B01h to obtain the spec packet directly from the
BIOS if necessary.
- This call gives information specific to a particular Syslinux
- derivative. The value returned in AL is the same as is
- returned in DL by INT 22h AX=0001h.
-
AX=000Bh [2.00] Get Serial Console Configuration
@@ -824,8 +833,8 @@ AX=0018h [3.30] Query custom font
AX=0019h [3.50] Read disk [SYSLINUX, ISOLINUX, EXTLINUX]
Input: AX 0019h
- EDX Sector number
- ESI Reserved - MUST BE ZERO
+ EDX Sector number (LSW)
+ ESI Sector number (MSW) [4.00]
EDI Reserved - MUST BE ZERO
CX Sector count
ES:BX Buffer address
diff --git a/doc/extlinux.txt b/doc/extlinux.txt
index 53f9f48..6974a51 100644
--- a/doc/extlinux.txt
+++ b/doc/extlinux.txt
@@ -97,9 +97,9 @@ preferred way to boot is:
- Install the MBR on *each disk*, and mark the RAID-1 partition
active.
-- Run "extlinux -i /boot" to install extlinux. This will install it on
- all the drives in the RAID-1 set, which means you can boot any
- combination of drives in any order.
+- Run "extlinux --raid --install /boot" to install extlinux. This
+ will install it on all the drives in the RAID-1 set, which means
+ you can boot any combination of drives in any order.
diff --git a/doc/gpt.txt b/doc/gpt.txt
index 14c1ee8..0909932 100644
--- a/doc/gpt.txt
+++ b/doc/gpt.txt
@@ -1,13 +1,10 @@
GPT boot protocol
-There is no official MBR-to-partition handover protocol defined for
-booting from disks partitioned using GPT partition tables with
-BIOS-style firmware. This is because the GPT partition format comes
-from the EFI spec, which thinks the universe is all going to be EFI.
-Sigh.
+There are two ways to boot a GPT-formatted disk on a BIOS system.
+Hybrid booting, and the new GPT-only booting protocol originally
+proposed by the author, and later adopted by the T13 committee in
+slightly modified form.
-There are thus two alternatives: hybrid booting, and defining a new
-protocol.
*** Hybrid booting ***
@@ -29,31 +26,16 @@ GPT disk with BIOS firmware.
*** New protocol ***
-This defines an alternative (experimental) booting protocol for GPT
-partitions with BIOS firmware. It maintains backwards compatibility
-to the extent possible. It is implemented by the file mbr/gptmbr.bin.
+This defines the T13-approved protocol for GPT partitions with BIOS
+firmware. It maintains backwards compatibility to the extent
+possible. It is implemented by the file mbr/gptmbr.bin.
- -> The PMBR
+The (P)MBR format is the normal PMBR specified in the UEFI
+documentation, with the first 440 bytes used for the boot code. The
+partition to be booted is marked by setting bit 2 in the GPT Partition
+Entry Attributes field (offset 48); this bit is reserved by the UEFI
+Forum for "Legacy BIOS Bootable".
-The PMBR (the first 512-byte sector of the disk) is divided up as
-follows:
-
- Offset Size Contents
- ---------------------------------------------------------
- 0 424 PMBR boot code
- 424 16 GUID of the boot partition
- 440 4 MBR-compatible disk ID
- 444 2 Magic number: 1D 9A
- 446 16 PMBR protective entry
- 462 48 PMBR null entries
- 510 2 Boot signature: 55 AA
-
-To change the bootable partition, verify that the magic number is
-present (to avoid corrupting software not compatible with this
-specification) and enter the GUID of the boot partition at offset
-424. It might be wise to verify that the data already there is a
-valid partition GUID already, or at least warn the user if that is not
-the case.
-> The handover protocol
@@ -66,11 +48,12 @@ form:
---------------------------------------------------------
0 1 0x80 (this is a bootable partition)
1 3 CHS of partition (using INT 13h geometry)
- 4 1 0xEE (partition type: EFI data partition)
+ 4 1 0xED (partition type: synthetic)
5 3 CHS of partition end
8 4 Partition start LBA
12 4 Partition end LBA
- 16 varies GPT partition entry
+ 16 4 Length of the GPT entry
+ 20 varies GPT partition entry
The CHS information is optional; gptmbr.bin currently does *NOT*
calculate them, and just leaves them as zero.
@@ -80,9 +63,7 @@ partition entry), except that the information is provided
synthetically. The MBR-compatible fields are directly usable if they
are < 2 TB, otherwise these fields should contain 0xFFFFFFFF and the
OS will need to understand the GPT partition entry which follows the
-MBR one. The "!GPT" magic number in EAX and the 0xEE partition type
+MBR one. The "!GPT" magic number in EAX and the 0xED partition type
also informs the OS that the GPT partition information is present.
-Currently, this is compatible with Syslinux as long as the Syslinux
-partition is < 2 TB; this probably will be improved in a future
-version.
+Syslinux 4.00 and later fully implements this protocol.
diff --git a/doc/memdisk.txt b/doc/memdisk.txt
index c7244ab..fecf2dc 100644
--- a/doc/memdisk.txt
+++ b/doc/memdisk.txt
@@ -139,6 +139,7 @@ h) Some systems without a floppy drive have been known to have
doesn't work, you can use the option:
nopass Hide all real drives of the same type (floppy or hard disk)
+ nopassany Hide all real drives (floppy and hard disk)
Some interesting things to note:
@@ -190,13 +191,14 @@ The MEMDISK info structure currently contains:
[ES:DI+2] byte MEMDISK minor version
[ES:DI+3] byte MEMDISK major version
[ES:DI+4] dword Pointer to MEMDISK data in high memory
- [ES:DI+8] dword Size of MEMDISK data in 512-byte sectors
+ [ES:DI+8] dword Size of MEMDISK data in sectors
[ES:DI+12] 16:16 Far pointer to command line
[ES:DI+16] 16:16 Old INT 13h pointer
[ES:DI+20] 16:16 Old INT 15h pointer
[ES:DI+24] word Amount of DOS memory before MEMDISK loaded
[ES:DI+26] byte Boot loader ID
- [ES:DI+27] byte Currently unused
+ [ES:DI+27] byte Sector size as a power of 2
+ (If zero, assume 512-byte sectors)
[ES:DI+28] word If nonzero, offset (vs ES) to installed DPT
This pointer+16 contains the original INT 1Eh
diff --git a/doc/menu.txt b/doc/menu.txt
index c912c1d..e2dd1e1 100644
--- a/doc/menu.txt
+++ b/doc/menu.txt
@@ -309,7 +309,12 @@ MENU NOSAVE
On the other hand, it handles changes in the configuration
file gracefully.
- The MENU SAVE information can be cleared with
+ NOTE: In software RAID-1 setups MENU SAVE only stores the
+ default label on the actual boot disk. This may lead to
+ inconsistent reads from the array, or unexpectedly change the
+ default label after array resynchronization or disk failure.
+
+ The MENU SAVE information can be fully cleared with
"extlinux --reset-adv <bootdir>".
A MENU SAVE or MENU NOSAVE at the top of a (sub)menu affects
@@ -492,16 +497,23 @@ MENU VSHIFT 0
screen (25 for text mode, 28 for VESA graphics mode.)
-F1 textfile background
+F1 textfile [background]
...
-F12 textfile background
+F12 textfile [background]
Displays full-screen help (also available at the command line.)
The same control code sequences as in the command line
interface are supported, although some are ignored.
- Additionally, a second argument allows a different background
- image (see MENU BACKGROUND for supported formats) to be displayed.
+ Additionally, a optional second argument allows a different
+ background image (see MENU BACKGROUND for supported formats)
+ to be displayed.
+
+
+MENU HELP textfile [background]
+
+ Creates a menu entry which, when selected, displays
+ full-screen help in the same way as the F-key help.
The menu system honours the TIMEOUT command; if TIMEOUT is specified
diff --git a/doc/syslinux.txt b/doc/syslinux.txt
index 76cae24..51d1332 100644
--- a/doc/syslinux.txt
+++ b/doc/syslinux.txt
@@ -163,11 +163,10 @@ IPAPPEND flag_val [PXELINUX only]
... based on the input from the DHCP/BOOTP or PXE boot server.
- THE USE OF THIS OPTION IS NOT RECOMMENDED. If you have to use
- it, it is probably an indication that your network configuration
- is broken. Using just "ip=dhcp" on the kernel command line
- is a preferrable option, or, better yet, run dhcpcd/dhclient,
- from an initrd if necessary.
+ NOTE: The use of this option is no substitute for running a
+ DHCP client in the booted system. Without regular renewals,
+ the lease acquired by the PXE BIOS will expire, making the
+ IP address available for reuse by the DHCP server.
2: indicates that an option of the following format
should be generated and added to the kernel command line:
@@ -180,6 +179,14 @@ IPAPPEND flag_val [PXELINUX only]
This allows an initrd program to determine from which
interface the system booted.
+ 4: indicates that an option of the following format
+ should be generated and added to the kernel command line:
+
+ SYSUUID=<system uuid>
+
+ ... in lower case hexadecimal in the format normally used for
+ UUIDs (same as for the configuration file; see pxelinux.txt.)
+
LABEL label
KERNEL image
APPEND options...
More information about the Syslinux-commits
mailing list