Grub4dos Internal variables and functions

counter customisable

The following is a list of some grub4dos internal variables and functions from a 2012 or later version of a chenall build of grub4dos (as included with the latest version of RMPrepUSB).

Grub4dos variables have a maximum name length 8 characters and maximum value size of 512 characters.

e.g.
set FRED1234=Hi
set FRED12345=Lo
echo %FRED1234%
echo %FRED12345%
set

Lo
Lo
FRED1234=Lo

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 (use delmod to remove the modules from memory after use).

#clear all variables
set *

Strings

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)

e.g

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

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). p is the path and d is the drive name.

%0=/xx/fred.g4b
%~nx0=fred.g4b
%~x0=.g4b
%~n0=fred
%~dp0=(hd0,0)/xx/
%~dpnx0=(hd0,0/xx/fred.g4b
%~nx0=fred.g4b
%~p0=/xx/

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

Internal named variables

grub4dos has a few predefined variables - these can be used in a grub4dos command - e.g. echo %@date% or set d=%@date%

These are case sensitive:

@date   - e.g. 2012-04-08
@time  - e.g.  15:29:11
@random - 0 to 32767  - e.g. set /a num1to10=%@random% / 3277 + or set /a num1to10=%@random:~-1,1% + 1
@root - e.g. (hd0,0)
@path - e.g. (bd)/BOOT/GRUB/
@retval - e.g. 1
?_BOOT - e.g. (hd0,0)
?_WENV
?_UUID  - set after uuid command - e.g. uuid (bd)
?  - result of last command - e.g.  cat --locate=string --number=1 /myfile && set offset=%?% && echo string found at %offset%    prints 0x1de

Fn calls

You can call an internal function like sprintf within a grub4dos menu or a grub4dos batch file. For example:
set a=aa
set b=bbb
call Fn.0 0 "stringa=%s stringb=%s" %a% %b%

this prints on the display
stringa=aa stringb=bbb

Here is a list of the Fn calls. I don't know all the details for all the parameters, but each parameter should be separated by a space.
Note that Fn. is case sensitive and must have a capital F and a lowercase n.

0 grub_sprintf - e.g. call Fn.0 0 "id="%s","%1"" %p_hwid%
1 grub_putstr
2 putchar - e.g. call Fn.2 49 prints '1'
3 get_cmdline_obsolete
4 getxy  The return value is ((X << 8) | Y).
5 gotoxy - e.g. call Fn.5 0 2 set cursor pos to beginning of line 11
6 cls
7 wee_skip_to was obsolete setcursor
8 nul_terminate
9 safe_parse_maxint_with_suffix
10 substring
11 grub_strstr - e.g. call Fn.11 0x6000 "$"
12 grub_strlen - e.g. call Fn.12 "freddy" && echo %@retval% - prints 6
13 grub_strtok - e.g. set /a p_hwid=0x40000 && call Fn.13 %p_hwid% "," or call Fn.13 0 "," || exit
14 grub_strncat
15 grub_strcmp  compare two strings - e.g. call Fn.15 XXX XXX && echo %@retval%  returns 0  (or -1 if no match)
16 grub_strcpy
17 reserved
18
19 getkey - gets a kbdchar
20 checkkey Check if any input character is available.
21
22 grub_memcmp
23 grub_memmove
24 grub_memset

25
26 grub_open - e.g. directly call grub_open file function it will put filesize at memory 0x8320 - this works well for non-compressed files too. call Fn.26 /myfile.gz && set /a filesize=*0x8320
27 grub_read
28 grub_close

29
30
31
32 devread
33 devwrite
34 next_partition
35 open_device
36 real_open_partition
37 set_device
38
39
40
41 parse_string
42 hexdump - e.g. call Fn.42 0x8000 0 3 - list 3 hex bytes at 0x8000
43 skip_to
44 builtin_cmd
45 get_datetime
46 find_command
47
48
49 get_mmap_entry
50 grub_malloc
51 grub_free51
52 list_partitions
53 realmode_run - executes a BIOS interrupt in real mode - e.g. see date.g4b batch file for example.
54 reserved for wee
55 reserved for wee
56 reserved for wee
57 reserved for wee
58 reserved for wee
59 reserved for wee
60 reserved for wee
61 dir - e.g. Fn.61 /dir/
62 print_a_completion
63 print_completions
64 lba_to_chs
65 probe_bpb
66 probe_mbr
67 unicode_to_utf8 e.g. call Fn.67 *0x82d0 0x60000 3     cat (md)0x300+1,1 | set nt_ver=NT
68 rawread
69 rawwrite
70 setcursor e.g. call Fn.70 0 to disable cursor and splashimage
71 grub_tolower
72 grub_isspace
73 grub_sleep e.g. call Fn.73 3 to sleep for 3 secs
74 mem64
75 envi_cmd
76 strncmpx
77 rectangle
78 get_cmdline


Internal Variable Locations held in memory

When grub4dos loads into memory, it will store certain internal, local values at defined places within memory. Sometimes it is useful to read or write to these locations.

For instance, the grub4dos version number is held at location 0x8278 in memory. So you can check what version the user is running by adding these lines to your grub4dos menu.lst file:

 checkrange 20120201:-1 read 0x8278 || pause --wait=3 Please use grub4dos-0.4.5c-2012-02-01 or later! && exit 1

This checks the value of 0x8278 to ensure it is between 20120201 (the date that the grub4dos version was made) and -1 (which is the largest possible number). If this check fails then the message is displayed with a 3 second countdown and then the menu is exited.

Some variable locations + examples are given in the lists below:

Address Length Description
========= ======== ==============================================
0000:8208         4 (DWORD) install_partition (the boot partition)
0000:8280         4 (DWORD) boot_drive (the boot drive)  set /A BD=*0x8280&0xf0      if %BD%==0x80 echo We booted from a hard disk!
0000:8284         4 (DWORD) pxe_yip (your ip)
0000:8288         4 (DWORD) pxe_sip (server ip)
0000:828C         4 (DWORD) pxe_gip (gateway ip)
0000:8290         8 (QWORD) filesize (file size by last "cat --length=0")
0000:8298         4 (DWORD) saved_mem_upper (extended memory size in KB)
0000:829C         4 (DWORD) saved_partition (current root partition)
0000:82A0         4 (DWORD) saved_drive (current root drive)
0000:82A4         4 (DWORD) no_decompression (no auto gunzip)
0000:82A8         8 (QWORD) part_start (start sector of last partition)
0000:82B0         8 (QWORD) part_length (total sectors of last partition)


0x8217 current configfile path and name e.g. call Fn.0 0 0x8217
0x826C BSS start address (4 bytes)
0x8274 autonumber boot entries with a hyphen after the number - write 0x8274 0x2d01
0x8276 set /a CURDEF=*0x8276 & 0ff gets current menu item number as a variable CURDEF
0x8278 check version of grub4dos - e.g. checkrange 20120201:-1 read 0x8278 || pause --wait=3 Please use grub4dos-0.4.5c-2012-02-01 or later! && exit 1
0x8280 Disk type - checkrange 0x80 read 0x8280 && pause --wait=3 I am Hard Disk 0
0x8290 Length of file in bytes -e.g cat --length=0 /myfile.iso && set /a LEN=*0x8290 && echo Length of file is %LEN% bytes
0x8298 maximum free memory in KB starting at 1M and below 4G (memory may NOT be contiguous) # calculate sizes in MB of iso and available memory - set /a MEMSIZE=*0x8298&0xFFFFFFFF>>10 && cat --length=0 && /myfile.iso && set FSize=*0x8290>>20 && if %FSize%>=%MEMSIZE% && echo Need More memory!
0x82BC CPU type - iftitle [checkrange 0,1 read 0x82Bc] 32bit system
0x82D0 rd_base
0x82D8 rd_size
0x8320 to get the expanded length of a compresses .gz file - use: cat --length=1 /myfile.gz && set /a filesize=*0x8320
# Or directly call grub_open file function it will put filesize at memory 0x8320 - this works well for non-compressed files too. call Fn.26 /myfile.gz && set /a filesize=*0x8320
0x8328 filepos ptr

set /a IP1 = *0x8284 & 0xFF
set /a IP2 = *0x8285 & 0xFF
set /a IP3 = *0x8286 & 0xFF
set /a IP4 = *0x8287 & 0xFF
set YIP = %IP1%.%IP2%.%IP3%.%IP4%


# get the UUID of a boot volume (note: do NOT use && to join these lines!)
uuid (bd) > nul
set UUID=%?_UUID%

or you can use just one line:
uuid () && call set UUID=%^?%

Note that %^?% is used because %?% would be treated as a literal string and UUID would be set to %?% if ^? was not used!
^ anywhere inside a variable means do not translate to a variable - e.g. set a=%bb^bbb% returns a=%bbbbb%

New operators (chenal grub4dos versions April 2013 and later)

The && and || operators do not affect the environment until the whole line has been executed - e.g.

set a=1 && echo %a%

does not echo '1' because the environment is not updated until after the whole line has been executed. There are now three new operators:

;;  - used to separate commands on the same line - e.g.

set a=1 ;; echo %a% ;; # This is a comment ;; set /a b=%a% + 1

;& - as ;; but the next command is only executed if the result of the previous command was true, e.g.

set a=menu.lst ;; if exist /%a% ;& echo %a% exists

;| - as ;; but next command is only executed if the previous command was falser