Grub4dos Internal variables, memory areas, advanced features and function calls

counter customisable

eBook (PDF)

'Getting started with grub4dos' - Latest eBook PDF for 2020!
Complete grub4dos 0.4.6a guide with exercises and full command reference.

The following is a list of some grub4dos internal variables and functions from a 2013 or later version of a chenall build of grub4dos (as used in RMPrepUSB).

Memory areas used by grub4dos (minimum 64MB)

The physical memory address range from 1M to 32M+ is reserved for grub4dos internal code and data. Grub4dos may fail to run on systems with less than 64MB of RAM. Ideally users should not use this range.
Grub4dos and Linux can use RAM above 32MB.
Some areas below 1MB are also used by grub4dos.
Some use of (md)0x300 is relatively safe if low memory is required.

Grub4dos executes grub4dos executables and kernel payloads at 32MB in memory, therefore it is best to use memory areas well above 64MB for any memory workspace if you intend to call grub4dos executables after loading kernel files, etc.

Since grub4dos uses areas above 32MB, a 64MB system is the minimum requirement for grub4dos 0.4.6a.

Note: In grub4dos, batch files and programs run in the same memory buffer space as the 'kernel' command uses. Therefore you cannot use the kernel command directly from a batch file or grub4dos program. To workaround this, either allocate memory to move the buffer by using call Fn.50 0x200000 as the very first line in menu.lst OR use configfile, e.g.

echo kernel /xxx/vmlinuz aaa bbb ccc > (md)0x220+1
echo initrd initrd.gz >> (md)0x220+1
configfile (md)0x220+1

(md) is a memory 'device'. (md)x+y where x is the start sector in memory and y is the length of memory in sectors (e.g. (md)4+2 = start at 2KB in memory for a length of 1KB. Note that the BIOS uses low memory!

Grub4dos use of memory - (md) uses 512-byte 'sectors'

0x0007000 CMD line buffer
0x0008200 320K fixed variables + grldr program = (md)0x41 to (md)0x300
0x0050000 to the end of low memory is used by gfxmenu
0x0030000 64k sector buffer for current device = (md)0x180 to (md)0x1FF
0x0040000 unused (user) = (md)0x200 to (md)0x227
0x0045000 environment variables = (md)0x228 to (md)0x288 approx.
0x0060000 end of grub4dos variables + wkspace = (md)0x300 to (md)0x3DF
0x007C000 used to load boot code, etc. = (md)0x3E0...
0x0090000 may be used by BIOS (avoid) = (md)0x480 to (md)0x4FF
0x00A0000 graphics memory (reserved) = (md)0x500 to (md)0x5FF
0x00C0000 BIOS area (reserved) = (md)0x600 to (md)0x7FF
0x0100000 may be used by BIOS (avoid) = (md)0x800 best to avoid up to (md)0x880
0x02B0000 2.6MB HMA_ADDR = (md)0x1580
0x03E0000 FSYS_BUF = (md)0x1F00 to (md)0x1F40
0x0800000 8M for mem array workspace = (md)0x4000 to (md)0x7FFF
0x0A00000 10M-14M for page map = (md)0x5000-(md)0x6FFF
0x0F00000 15M-16M used by some systems (avoid) = (md)0x7800-(md)0x7FFF
0x1000000 16M-19M used to store background bmp = (md)0x8000-(md)0xD460 (end of buffer depends on size of bitmap, 1920x1440=0xD460, 1280x800=0x9F40, 1024x768=0x9800, 800x600=0x8EA6)
0x1800000 24MB Unifont area = (md)0xC000-0xFFFF
0x2000000 32MB Reserved memory area = (md)0x10000 (e.g. used by grub4dos for file decompression, etc.)
0x2800000 40MB Linux temp memory area = (md)0x14000

(md)0x880-(md)0x1580 may be usable (untested)??
Avoid 15MB to 16MB as used by some BIOSes/chipsets as echo of 1MB-2MB area! (md)0x7800-7FFF

Easy2Boot use (md)0x3000, (md)0x9F00, (md)0xA000, (md)0xB000.

Avoid below (md)0x300 and (md)0x4000 to (md)0x7FFF area.
Preferably use (md)0x10000 and above (above 32MB). I have also used there areas without problems so far...

Use of around (md)0x8000 to 0x9800 can cause corruption of bitmap background when a menu is displayed in 1024x768 mode (even more used in higher res modes!).
However wenv/insmod seems to load files above 32MB - therefore use above 50MB = (md)0x19000 to be safe!

Many BIOSes use the last part of segment 9000:0 for a scratchpad. All IBM-compatible BIOSes use A000:0 - F000:FFFF.

Black areas are normally unused by grub4dos and IBM PC BIOS and hardware but are not necessarily safe to use!

50 40 0.039 A000 000A00:0
60 48 0.0468 C000 000C00:0
80 64 0.0625 10000 001000:0
220 272 0.265 44000 004400:0
300 384 0.375 60000 006000:0
400 512 0.5 80000 008000:0
500 640 0.625 A0000 00A000:0
600 768 0.75 C0000 00C000:0
700 896 0.875 E0000 00E000:0
800 1024 1 100000 010000:0
880 1088 1.0625 110000 011000:0
900 1152 1.125 120000 012000:0
a00 1280 1.25 140000 014000:0
b00 1408 1.375 160000 016000:0
c00 1536 1.5 180000 018000:0
d00 1664 1.625 1A0000 01A000:0
e00 1792 1.75 1C0000 01C000:0
f00 1920 1.875 1E0000 01E000:0
1000 2048 2 200000 020000:0
2000 4096 4 400000 040000:0
3000 6144 6 600000 060000:0
3100 6272 6.125 620000 062000:0
3200 6400 6.25 640000 064000:0
4000 8192 8 800000 080000:0
5000 10240 10 A00000 0A0000:0
6000 12288 12 C00000 0C0000:0
7000 14336 14 E00000 0E0000:0
8000 16384 16 1000000 100000:0
9000 18432 18 1200000 120000:0
a000 20480 20 1400000 140000:0

(md)0x200 - 0x227 (20K) this seems to be used by chenall, et al. and so is probably safe!
(md)0x300 - 0x3DF (114k) 384-600KB approx. (0x3E0 may be used for chainloading by grub4dos)
(md)0x1F40 - 0x3FFF (4M) I have used (md)0x3000-(md)0x3300 without problems
(md)0x9800 - 0xBFFF(5M) Safe if only using graphics mode 1024x768 or lower resolutions E2B used 0xA000+0xA0
(md)0xD800 - 0xFFFFF (can start from 0x9800 as long as not using higher Res than 1024x768)
(md)0x19000+ (50MB+)

As most systems will have over 64MB of memory, use memory after (md)0x20000 to be ultra safe!

Using grub4dos variables

grub4dos environment variables are stored as strings.

Each Grub4dos variable can have a maximum name length 8 characters and each variable holds a maximum size of 511 characters or bytes. The variable name is case sensitive, e.g.

set a=1
set A=2


Environment names of 10 or more characters will cause an error.
Using a 9-character variable name can cause unexpected problems (FRED12345 in this example is shortened by grub4dos to FRED1234) ...

set FRED1234=Hi
set FRED12345=Lo
echo %FRED1234%
echo %FRED12345%


Note: Variables and their values are stored in memory and may share the same workspace area as modules loaded using the 'insmod' command. You may get crashes if you define too many variables and have lots of large modules loaded into memory (always use delmod to remove the modules from memory after use).

#clear all variables except fred
set * && set fred=%fred%

You can define leading spaces in a variable and have characters like && or ;; by enclosing the argument in double-quotes (must start as "<variable>= with no spaces
set "a= fred && doris"

Be careful using && or || as the environment is not changed until the whole line has been executed - e.g. the following line will not print HELLO the first time it is run because A is not set until after the whole line has been executed:

set A=HELLO && echo %A%

(grub4dos will replace all %variables% in the whole line with their values first before executing the whole line).

Get the number of characters in any variable - this example prints 5
# set command will return the length
set a=freda
# do stuff here...
# get length of a into @retval
set a=%a%
echo Number of characters in variable a = %@retval%

To display all variables beginning with AB use:
set AB

You can use IF EXIST to test for the existence of a variable
if exist FRED echo Variable FRED exists!

Note: Using ^ anywhere inside % signs will prevent grub4dos from expanding the variable - e.g. %^aa% will be changed by the grub4dos pre-processor to %aa% - it will not be replaced by the value of aa.

Increasing the variable space (not recommended)

Grub4dos has space for only 60 string variables, each one can have a value of up to 511 bytes in size (plus one byte for 'end-of'string').

# check if a variable has been defined
if exist FRED1234 echo FRED1234 is set to %FRED1234% || echo Variable FRED1234 has not been defined!

In the latest versions of grub4dos (15 May 2013 and later) you can extend the variable space using an undocumented @extend command:
You can set up to max 65,536 variables using @extend.

set @extend BASE_ADDR SIZE

The BASE_ADDR is the memory start of extended variable.
SIZE is how many variables it will extended by (MAX is 0xFFFF)

e.g. add 10 variables (so we can have 70 variables in total) at 0x40000.

set @extend 0x40000 10

this needs memory (((10+63)/64) + 10)*512 = 5632. You must confirm the BASE_ADDR has enough space.

setlocal/endlocal will not work correctly however as any variables over the 60 that are set inside a setlocal section will remain after an endlocal!
So if you are using @extend and setlocal/endlocal, be sure to not use more than 60 variables inside the setlocal/endlocal segments!

set @extend 0x40000 10
set *
set 70 variables here...
>>> 10 variables will be listed!

The command:

set @extend

will display:


The first number is the base address in memory where the extra variable names are stored. The second number is the next unused block. The last number is the number of extra variables (above 60) that can be stored (10 variables = 200h*10 = 200 sectors from 0x40000 to 0x401FF).


You can get a substring of any variable like this: %variablename:~startpos,endpos%

The startpos shows where the substring begins ( + position from the beginning, - position from the end)
The endpos shows where it ends ( + position from the beginning, - position from the end)


set a=0123456789abcdefghijklmnopqrstuvwxyz
echo %a:~0,3% displays 012
echo %a:~2,3% displays 234
echo %a:~-3,3% displays xyz
echo %a:~3% displays 3456789abcdefghijklmnopqrstuvwxyz
echo %a:~3,-2% displays 3456789abcdefghijklmnopqrstuvwx
echo %a:~,-2% displays 0123456789abcdefghijklmnopqrstuvwx

A header file which may help if you understand C code can be found here.

Example - test string length of KEY is exactly 29 characters
set KL=0
if not "%KEY:~29,1%"=="" set KL=1 && echo TOO LONG!
if "%KEY%"=="%KEY:~0,28%" set KL=2 && echo TOO SHORT!
if not "%KL%"=="0" pause --wait=3 INVALID PRODUCT KEY "%KEY%"! && configfile /menu.lst

Filename strings in batch files (limitations)

Max no lines = 2048 in a batch file, Max. no. labels in a batch file = 128, file must start with !BAT on first line.

In a batch file, %0 is the full path of the batch file itself (if the batch file is in the root then no leading / is output), %~nx0 is the batch files filename + extension, %~n0 is just the filename and %~x0 is just the extension (e.g. .gb4).

n is filename, x is extension, p is the path and d is the drive name.

%0=/xx/fred.g4b (if in root then fred.g4b)
%~pnx0=/xx/fred.g4b (if in root then /fred.g4b)
%~0=parameter without quotes
%~f0=fully path of filename - e.g. if %0=fred.inf then %~f0=(hd1,0)/dir1/dir2/fred.inf if root was set to (hd1,0)/dir1/dir2

If you pass more than one filename to a batch file, %1 will be the second parameter, %2 the third, etc. %* is all parameters.

Batch file to get all parameters as arg1...argn and argc as number of parameters:

set argc=0
if "%1"=="" goto :fin
set /a argc=%argc%+1 > nul
set arg%argc%=%1
goto :LOOP

Note: BEWARE! in batch files beware of %0 %1 %2 accidents! e.g.

set f=3
echo %f%2

will not display 32 (it displays %f because %1, %2 %3 special variables are substituted first, so grub4dos translates this to %f+%2) - instead use this...

set f=3
echo %f%%2

%% in a batch file is reduced to %. Since %%2 does not mean anything to grub4dos on the first substitution pass, we get the expected answer.

If you have a filename or full or partial filespec, you can get bits of it like this:

# set current path to /_ISO folder
root ()/_ISO > nul
set file=/test/my.iso
call :show %file%

echo %%~d1=%~d1 %%~p1=%~p1 %%~n1=%~n1 %%~x1=%~x1 %%~f1=%~f1
goto :eof

we get:

%~d1=(hd0,0) %~p1=/_ISO/test/ %~n1=my %~x1=.iso %~f1=(hd0,0)/_ISO/test/my.iso

Accessing numbered variables

If we have a number of variables FRED1, FRED2, FRED3, etc, and we want to print out the value of each, we can use a counter like this

set FRED1=A
set FRED2=B
set FRED3=C
set N=0

set /a N=%N%+1 > nul
call echo %^FRED%N%%%
if %N%<=2 goto :LOOP


Note that using ^ anywhere inside a variable prevents it from being translated into a value. So %^FRED%N%%% gets translated by 'call' to %FRED1% and then echo displays the FRED1's value.

If not using a batch file use call echo %^FRED%N%% instead (in a batch file, %%=%).