Jump to content











Photo
* * * * * 1 votes

dynamic menu entry to load a Linux distro

linux dynamic

  • Please log in to reply
25 replies to this topic

#1 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 19 May 2013 - 11:14 PM

Hi.
I'm trying to make a menu entry to start a specific Linux distro (usually installed on the USB drive).

Until now I used this:





title Start Linux
root (hd0,n)
kernel /boot/kernel_name root=UUID=[...] [other kernel parameters]
initrd /boot/initrd_name

 

The problem is that it's very "static" (instead of "dynamic"). If I change the Linux kernel I have to modify it manually. It's not a big issue to change some numbers (most of the times) but still...
Another thing: if there is more than one kernel to be able to show options to boot with each one (a menu entry for each one).

What I've done so far:

In menu.lst I add:
 





title Start Linux from USB drive
set FOUNDS=0
set FOUNDM=0
call /findkrnl.g4b
if "%FOUNDS%"=="1" kernel /boot/%KERNEL% root=UUID=[...] [kernel parameters] && initrd /boot/initramfs-%KERVER%.fc18.i686.img && boot
if "%FOUNDM%"=="1" write (md)0x220+8 %FK1%%FK2%%FK3%%FK4%%FK5%%FK6%%FK7%%FK8%%FK9%%FK10%title\r\nroot\r\ntitle Return to main menu...\r\nroot (bd)\r\nconfigfile /menu.lst\r\n\0 > nul && configfile (md)0x220+8
root (bd)
configfile /menu.lst

 


Adding "configfile /menu.lst" to the end seems redundant but it is necessary so the menu entry should be selected with the up/down keys. Without this line you can't select it; you'll have to use left/right keys.
Is there a better "workaround"?

Also, adding "&& boot" seems redundant since it's not usually needed but in this case Linux won't boot because of the "configfile /menu.lst" line...

findkrnl.g4b:





!BAT
clear
find --set-root --ignore-floppies --ignore-cd uuid () [...] > nul || echo Linux partition not found! Returning to main menu... && pause --wait=5 && goto :finish
ls /boot/ > (md)0x220+8 || echo /boot not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
cat --locate=" vmlinuz-" (md)0x220+8 > (md)0x300+1 || echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
cat --skip=1 --locate=" " (md)0x300+1 > nul && goto :multi
cat --skip=1 (md)0x300+1 | set VMPOSB=
debug -1
set /a VMPOSB=0x%VMPOSB%+1
debug normal
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if "%VMPOSE%"=="" echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
debug -1
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB%
debug normal
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
if not exist /boot/%KERNEL% echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
debug -1
set /a KERVERB=%VMPOSB%+8
set /a KERVERL=0x%VMPOSE%-%KERVERB%
debug normal
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
if not exist /boot/initramfs-%KERVER%.fc18.i686.img echo initrd not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
set FOUNDS=1
goto :finish
:multi
set SKIPPED=1
set ENDPOS=0
set N=1
:loop
cat --skip=%SKIPPED% --locate=" " --number=1 (md)0x300+1 | set LE=
if "%LE%"=="" goto :le0
debug -1
set /a ORGLE=%LE%
set /a LE=0x%LE%-%SKIPPED%
debug normal
cat --skip=%SKIPPED% --length=%LE% (md)0x300+1 | set VMPOSB=
debug -1
set /a SKIPPED=0x%ORGLE%+1
debug normal
goto :endle
:le0
cat --skip=%SKIPPED% (md)0x300+1 | set VMPOSB=
set ENDPOS=1
:endle
debug -1
set /a VMPOSB=0x%VMPOSB%+1
debug normal
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if "%VMPOSE%"=="" goto :finish
debug -1
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB%
debug normal
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
if exist /boot/%KERNEL% goto :ifkerx
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:ifkerx
debug -1
set /a KERVERB=%VMPOSB%+8
set /a KERVERL=0x%VMPOSE%-%KERVERB%
debug normal
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
if exist /boot/initramfs-%KERVER%.fc18.i686.img goto :ifintx
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:ifintx
set FK%N%=title start Linux with %KERVER% kernel\r\nkernel /boot/%KERNEL% root=UUID=[...] [kernel parameters]\r\ninitrd /boot/initramfs-%KERVER%.fc18.i686.img\r\n
set FKV%N%=%KERVER%
debug -1
set FOUNDM=1
set /a N=%N%+1
debug normal
if "%N%"=="11" goto :endloop
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:endloop
if "%FOUNDM%"=="0" echo No valid boot files found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
if "%N%"=="2" set FOUNDM=0 && set FOUNDS=1 && set KERNEL=vmlinuz-%FKV1%.fc18.i686 && set KERVER=%FKV1%
:finish

 


It works almost fine.
I would appreciate any tip to help me improve speed, accuracy, memory usage and so on.
Also I'm trying to find a way to show the menu entries in ascending order, from the oldest kernel to the newest.
I know how to do a "bubble sort" but the problem is comparing the strings (FK%N%).
First I will have to divide them into "parts":
3.9.2-200 >> 3 9 2 200
But I couldn't find a function to search for a character or a substring in a string. "cat" would of been great but it works only with files...
After that I will have to compare each of the corresponding "parts". The problem is that I don't know a way to find if a value is higher or lower than other value, only to know if they are equal or not.

Could you please help me with these...?
Thank you.

Regards, David



#2 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 20 May 2013 - 08:12 AM

Have you seen my page here?  You can get substrings. If they are a number then you can test with if %A%>=%B%   (or <=) - info here.

 

You can put all the kernel, initrd commands in the batch file too - they don't have to be in the menu. Use boot to end a menu to make it selectable.

 

e.g. 

title Start Linux from USB drive
call /findrunkrnl.g4b

boot

 

Your counting seems a bit odd (if VMPOSB gets to 10 then the next number will be 17!)

 

set /a VMPOSB=0x%VMPOSB%+1

 

why not just

set /a VMPOSB=%VMPOSB%+1

 

You don't need all these debug lines. 

 

Use 

set /a VMPOSB=%VMPOSB%+1 > nul

 

to stop any line echoing to the screen.

 

HTH



#3 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13748 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 20 May 2013 - 08:15 AM

Have you looked in WENV?

http://reboot.pro/to...b4dos/?p=169180

 

BTW, nothing prevents you to use a memory space to "make a file" and then use cat on it.

Example:

http://reboot.pro/to...-boot/?p=171589

 

:cheers:

Wonko



#4 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 20 May 2013 - 04:32 PM

Thank you guys for your help.
 

 

Have you seen my page here?

 


Yes, that's the "Bible" :D I've been reading it and using it for months now... Thank you very much for such useful guides.
 

 

You can get substrings.

 


I know that but the problem is that I CAN'T SEARCH for a substring. For example I want to search for '.' or '-'. This way I can extract those numbers no matter how many digits they have.
 

 

If they are a number then you can test with if %A%>=%B% (or <=) - info here.

 


<= and >= are good but not 100% what I need: < and >. When I compare 2 numbers I have to be sure that it's higher not higher or equal. Without them the sorting isn't possible.
Oh, by the way, how can I be sure that I compare numbers and not the string made by the digits? Why do I ask: because, as a string, 20 is lower than 9, but, as a number, obviously is higher.

 

You can put all the kernel, initrd commands in the batch file too - they don't have to be in the menu.

 


I tried that but they didn't worked. Seems that the write, kernel and initrd commands doesn't work well when they are added to the end of that batch file. I don't know why... I just noticed that outside of the batch file work.
 

 

Use boot to end a menu to make it selectable.

 


Make sens but the problem is those rare situations when no valid boot files are found, the code warns the user about that but still tries to use the boot command...
So far "configfile /menu.lst" works in all situations, boot command doesn't.
 

 

 

Your counting seems a bit odd (if VMPOSB gets to 10 then the next number will be 17!)

set /a VMPOSB=0x%VMPOSB%+1

why not just
set /a VMPOSB=%VMPOSB%+1
 

 

 

I used 0x%VMPOSB% after reading from 0x300+1 because in that "memory file" the positions are stored as hexa and I needed to convert to decimal.
Anyway I tested with 3 kernel files and it's ok.

 

You don't need all these debug lines.

Use
set /a VMPOSB=%VMPOSB%+1 > nul

to stop any line echoing to the screen.
 

 

 

You're right, I will use more "> nul".








 

 

Have you looked in WENV?

http://reboot.pro/to...b4dos/?p=169180


Yes I did but I don't have too much experience with WENV...
But what are the advantages of using WENV instead of usual code in my script (only, not talking globally)?
 

 

BTW, nothing prevents you to use a memory space to "make a file" and then use cat on it.

Example:

http://reboot.pro/to...-boot/?p=171589

 

In that thread last reply is a script of mine :D
Using write and then cat it should work (in theory). But I had problems with them when I tried to make that script. I don't remember if cat couldn't find the string or if that the code started to show strange errors when used but I remember clearly that it didn't worked.



#5 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 20 May 2013 - 04:39 PM

You can search for a substring using cat

 

 

echo 1234567 > (md)0x3000+1
cat --locate=45 --number=1 (md)0x3000+1 > nul
echo -n  Found 45 at position %?% in  && cat (md)0x3000+1


#6 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 20 May 2013 - 04:50 PM

We don't have > and <, but you can test by just subtracting or adding 1

.eg. if you want to see if the number is > 405

set mynumber=405
set /a a=%mynumber%-1
set b=405
set c=404
set d=406
if %b%>=%a% echo %b% is bigger than %mynumber%
if %c%>=%a% echo %c% is bigger than %mynumber%
if %d%>=%a% echo %d% is bigger than %mynumber%


#7 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13748 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 20 May 2013 - 05:21 PM

In that thread last reply is a script of mine  :D
...which I would define personally an overcomplex script :dubbio: :ph34r:
 
 
Using write and then cat it should work (in theory). But I had problems with them when I tried to make that script. I don't remember if cat couldn't find the string or if that the code started to show strange errors when used but I remember clearly that it didn't worked.
Maybe (just a possibility of course ;)) the cat is "right" and the code you wrote is wrong? :unsure:
 
About WENV, it has the check command working with strings:
 

CHECK - IF command to determine the command is equivalent to

usage: WENV check string1 compare-op string2 wenv-command

You can use one of the comparison symbols: ==,<>,>=,<=

where compare-op may be one of:
== Equal
<> Not equal
<= Less than or equal
>= Greater than or equal

Note: Note that when comparing the strings behind the lower-case comparison ignored.
Such as:
abc == ABC is true
aBc == abc is false
abc == aBc is true.
As long as the front part of a character is upper case, followed by the corresponding part of the match must be uppercase to
.
 
Which I thought was something you were looking for.

:cheers:
Wonko

#8 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 23 May 2013 - 01:02 AM

We don't have > and <, but you can test by just subtracting or adding 1

.eg. if you want to see if the number is > 405







set mynumber=405
set /a a=%mynumber%-1
set b=405
set c=404
set d=406
if %b%>=%a% echo %b% is bigger than %mynumber%
if %c%>=%a% echo %c% is bigger than %mynumber%
if %d%>=%a% echo %d% is bigger than %mynumber%

 

 

Yes, that could work but it will complicate the code even more that it will be.
Anyway I thought to simplify it a bit by using Fn call 15 grub_strcmp. It returns 1, 0 or -1.
I could try to insert some 0's into the string with kernel version: 3.9.2-200 >> 03.09.02-200 or 3.9.11-200 >> 03.09.11-200, and then use that Fn call.
Is there an easy way to do this or it can be done only manually?



 

 

...which I would define personally an overcomplex script


Maybe :D
 

 

Maybe (just a possibility of course ) the cat is "right" and the code you wrote is wrong?

 


It's not impossible... But I noticed that grub4dos has some problems when filling the memory with many variables. It starts to show strange errors...
Anyway it says in the "Bible": "You may get crashes if you define too many variables and have lots of large modules loaded into memory". So I will try to limit their number an clear them after use.
 

 

Which I thought was something you were looking for.

 

 


Yes, thank you.



#9 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 23 May 2013 - 04:12 AM

I made the code faster:
 

!BAT
clear
echo Please wait, searching for Linux partition...
uuid (hd0,1) [uuid_of_the_distro] > nul && root (hd0,1) > nul && goto :pfound
uuid (hd1,1) [uuid_of_the_distro] > nul && root (hd1,1) > nul && goto :pfound
uuid (hd2,1) [uuid_of_the_distro] > nul && root (hd2,1) > nul && goto :pfound
find --set-root --devices=h uuid () [uuid_of_the_distro] > nul && goto :pfound
echo Linux partition not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:pfound
echo Linux partition found, serching for boot files...
ls /boot/ > (md)0x220+8 || echo /boot not found! Returning to main menu... && pause --wait=5 && root (bd) > nul && goto :finish
cat --locate=" vmlinuz-" (md)0x220+8 > (md)0x300+1 || echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) > nul && goto :finish
cat --skip=1 --locate=" " (md)0x300+1 > nul && goto :multi
cat --skip=1 (md)0x300+1 | set VMPOSB=
set /a VMPOSB=0x%VMPOSB%+1 > nul
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if "%VMPOSE%"=="" echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) && goto :finish
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB% > nul
cat --skip=%VMPOSB% --length=%VMLEN% --locate=" " (md)0x220+8 > nul && echo kernel not found! Returning to main menu... && pause --wait=5 && root (bd) > nul && goto :finish
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
set /a KERVERB=%VMPOSB%+8 > nul
set /a KERVERL=0x%VMPOSE%-%KERVERB% > nul
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
set SKIPPED=
set VMPOSB=
set VMPOSE=
set VMLEN=
set ENDPOS=
set ORGLE=
set KERVERB=
set KERVERE=
write (md)0x220+2 timeout 0\r\n\r\ntitle start Linux 18 with %KERVER% kernel\r\nkernel /boot/%KERNEL% root=UUID=[uuid_of_the_distro] [other_kernel_parameters]\r\ninitrd /boot/initramfs-%KERVER%.fc18.i686.img\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nroot (bd) \> nul\r\nconfigfile /menu.lst\r\n\0 > nul
set KERNEL=
set KERVER=
configfile (md)0x220+2
goto :finish
:multi
set SKIPPED=1
set ENDPOS=0
set N=0
:loop
cat --skip=%SKIPPED% --locate=" " --number=1 (md)0x300+1 | set LE=
if "%LE%"=="" goto :le0
set /a ORGLE=%LE% > nul
set /a LE=0x%LE%-%SKIPPED% > nul
cat --skip=%SKIPPED% --length=%LE% (md)0x300+1 | set VMPOSB=
set /a SKIPPED=0x%ORGLE%+1 > nul
goto :endle
:le0
cat --skip=%SKIPPED% (md)0x300+1 | set VMPOSB=
set ENDPOS=1
:endle
set /a VMPOSB=0x%VMPOSB%+1 > nul
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if "%VMPOSE%"=="" goto :finish
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB% > nul
cat --skip=%VMPOSB% --length=%VMLEN% --locate=" " (md)0x220+8 > nul || goto :ifgk
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:ifgk
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
set /a KERVERB=%VMPOSB%+8 > nul
set /a KERVERL=0x%VMPOSE%-%KERVERB% > nul
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
set /a N=%N%+1 > nul
set FK%N%=title start Linux 18 with %KERVER% kernel\r\nkernel /boot/%KERNEL% root=UUID=[uuid_of_the_distro] [other_kernel_parameters]\r\ninitrd /boot/initramfs-%KERVER%.fc18.i686.img
set FKV%N%=%KERVER%
if %N%>=10 goto :endloop
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:endloop
set SKIPPED=
set VMPOSB=
set VMPOSE=
set VMLEN=
set ENDPOS=
set ORGLE=
set KERVERB=
set KERVERE=
set KERVER=

if "%N%"=="0" echo No valid boot files found! Returning to main menu... && pause --wait=5 && root (bd) > nul && goto :finish
if not %N%==1 goto :not1
write (md)0x220+2 timeout 0\r\n\r\ntitle start Linux with %KERVER% kernel\r\nkernel /boot/%FK1% root=UUID=[uuid_of_the_distro] [other_kernel_parameters]\r\ninitrd /boot/initramfs-%FKV1%.fc18.i686.img\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nroot (bd) \> nul\r\nconfigfile /menu.lst\r\n\0 > nul
set FK1=
set FKV1=
configfile (md)0x220+2
goto :finish
:not1

write (md)0x220+8 %FK1%\r\n%FK2%\r\n%FK3%\r\n%FK4%\r\n%FK5%\r\n%FK6%\r\n%FK7%\r\n%FK8%\r\n%FK9%\r\n%FK10%\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nroot (bd) \> nul\r\nconfigfile /menu.lst\r\n\0 > nul
set FK1=
set FK2=
set FK3=
set FK4=
set FK5=
set FK6=
set FK7=
set FK8=
set FK9=
set FK10=
set FKV1=
set FKV2=
set FKV3=
set FKV4=
set FKV5=
set FKV6=
set FKV7=
set FKV8=
set FKV9=
set FKV10=
configfile (md)0x220+8 /> nul
:finish

 

 

I'm curious why it does that...

Is there a better workaround/fix?



#10 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 23 May 2013 - 04:14 AM

Deleted (duplicated).

Forum error - it said that I don't have text but it added the reply...



#11 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 23 May 2013 - 07:06 AM

don't use write, use echo

 

echo -e sd sdasda %fred% asda >> (md)0x220+8

 

if you use ^ inside a %xxx% variable then it will not be converted into the value

 

e.g.

 

echo %fred^%    will echo %fred%

 

if you use echo -e -n then no carriage return will be printed at the end of the line, to make a new line use echo -e \nfred dddd

 

Use latest chenall grub4dos  21-05-2013



#12 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 23 May 2013 - 08:39 AM

I understand but what is the difference in using echo instead of write? Better speed? Because in inserting 0's or using kernel command after there is no difference...

 

I have the latest "Featured" 0.4.5c-2013-03-03



#13 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 28 May 2013 - 08:09 AM

I implemented setlocal/endlocal, the "pause" fix, the cycle for writing the dynamic menu and so on...
 



!BAT
clear
setlocal
echo Please wait, searching for Linux partition...
uuid (hd0,1) [uuid_of_the_Linux_partition] > nul && set LIND=(hd0,1) > nul && goto :pfound
uuid (hd1,1) [uuid_of_the_Linux_partition] > nul && set LIND=(hd1,1) > nul && goto :pfound
find --devices=h uuid () [uuid_of_the_Linux_partition] | set LIND=
if not "%LIND%"=="" goto :pfound
endlocal
echo Linux partition not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:pfound
echo Linux partition found, serching for boot files...
ls %LIND%/boot/ > (md)0x220+8 && goto :gls
endlocal
echo /boot not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:gls
cat --locate=" vmlinuz-" (md)0x220+8 > (md)0x300+1 && goto :kf1
endlocal
echo kernel not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:kf1
cat --skip=1 --locate=" " (md)0x300+1 > nul && goto :multi
cat --skip=1 (md)0x300+1 | set VMPOSB=
set /a VMPOSB=0x%VMPOSB%+1 > nul
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if not "%VMPOSE%"=="" goto :kf2
endlocal
echo kernel not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:kf2
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB% > nul
cat --skip=%VMPOSB% --length=%VMLEN% --locate=" " (md)0x220+8 > nul || goto :kf3
endlocal
echo kernel not found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:kf3
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
set /a KERVERB=%VMPOSB%+8 > nul
set /a KERVERL=0x%VMPOSE%-%KERVERB% > nul
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
write (md)0x220+2 timeout 0\r\n\r\ntitle start Linux with %KERVER% kernel\r\nkernel %LIND%/boot/%KERNEL% root=UUID=[uuid_of_the_Linux_partition] [other_kernel_parameters]\r\ninitrd %LIND%/boot/initramfs-%KERVER%.fc18.i686.img\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nconfigfile /menu.lst\r\n\0 > nul
endlocal
configfile (md)0x220+2
goto :finish
:multi
set SKIPPED=1
set ENDPOS=0
set N=0
set TMSZ=0
:loop
cat --skip=%SKIPPED% --locate=" " --number=1 (md)0x300+1 | set LE=
if "%LE%"=="" goto :le0
set /a ORGLE=%LE% > nul
set /a LE=0x%LE%-%SKIPPED% > nul
cat --skip=%SKIPPED% --length=%LE% (md)0x300+1 | set VMPOSB=
set /a SKIPPED=0x%ORGLE%+1 > nul
goto :endle
:le0
cat --skip=%SKIPPED% (md)0x300+1 | set VMPOSB=
set ENDPOS=1
:endle
set /a VMPOSB=0x%VMPOSB%+1 > nul
cat --skip=%VMPOSB% --locate=".fc18.i686" --number=1 (md)0x220+8 | set VMPOSE=
if "%VMPOSE%"=="" goto :finish
set /a VMLEN=0x%VMPOSE%+10-%VMPOSB% > nul
cat --skip=%VMPOSB% --length=%VMLEN% --locate=" " (md)0x220+8 > nul || goto :ifgk
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:ifgk
cat --skip=%VMPOSB% --length=%VMLEN% (md)0x220+8 | set KERNEL=
set /a KERVERB=%VMPOSB%+8 > nul
set /a KERVERL=0x%VMPOSE%-%KERVERB% > nul
cat --skip=%KERVERB% --length=%KERVERL% (md)0x220+8 | set KERVER=
set /a N=%N%+1 > nul
set FK%N%=title start Linux 18 with %KERVER% kernel\r\nkernel %LIND%/boot/%KERNEL% root=UUID=[uuid_of_the_Linux_partition] [other_kernel_parameters]\r\ninitrd %LIND%/boot/initramfs-%KERVER%.fc18.i686.img\r\n
set FKV%N%=%KERVER%
call call Fn.12 "%^FK%N%%%"
set /a TMSZ=%TMSZ%+%@retval% > nul
if "%ENDPOS%"=="1" goto :endloop
cat --skip=%SKIPPED% (md)0x300+1 > nul || goto :endloop
goto :loop
:endloop

if not "%N%"=="0" goto :bff
endlocal
echo No valid boot files found! Returning to main menu...
pause --wait=5 || goto :finish
goto :finish
:bff

if not %N%==1 goto :not1
write (md)0x220+2 timeout 0\r\n\r\ntitle start Linux 18 with %KERVER% kernel\r\nkernel %LIND%/boot/%FK1% root=UUID=[uuid_of_the_Linux_partition] [other_kernel_parameters]\r\ninitrd %LIND%/boot/initramfs-%FKV1%.fc18.i686.img\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nconfigfile /menu.lst\r\n\0 > nul
endlocal
configfile (md)0x220+2
goto :finish
:not1

set I=0
set OFFSET=0
set /a N=%N%+1 > nul
call Fn.12 "\r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nconfigfile /menu.lst\r\n\0"
set /a MBSZ=%TMSZ%+%@retval%/512+1 > nul
:wloop
set /a I=%I%+1 > nul
if %I%>=%N% goto :endwloop
call write --offset=%OFFSET% (md)0x220+%MBSZ% %^FK%I%%% > nul
call call Fn.12 "%^FK%I%%%"
set /a OFFSET=%OFFSET%+%@retval% > nul
goto :wloop
:endwloop
write --offset=%OFFSET% (md)0x220+%MBSZ% \r\ntitle\r\nroot\r\ntitle Return to main menu...\r\nconfigfile /menu.lst\r\n\0 > nul

endlocal && set MBSZ=%MBSZ%
configfile (md)0x220+%MBSZ%
:finish

 

 



#14 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 28 May 2013 - 08:45 AM

Why don't you use echo instead of write

echo start line > (md)0x220+0x50
echo  some stuff here >> (md)0x220+0x50
echo  some more stuff here >> (md)0x220+0x50

etc

 

Instead of using write and having to work out the offsets all the time (or did I miss something)?

 

you can use echo -e to use escape characters and echo -n to stop a carriage return being appended and call echo to do double %% translation.

 

Also, why do you need to calculate the size of the (md)0x220+xxxx device? Just use a big number that will always be more than you need.



#15 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 28 May 2013 - 10:12 AM

Why don't you use echo instead of write




echo start line > (md)0x220+0x50
echo  some stuff here >> (md)0x220+0x50
echo  some more stuff here >> (md)0x220+0x50

etc

 

Instead of using write and having to work out the offsets all the time (or did I miss something)?

 

you can use echo -e to use escape characters and echo -n to stop a carriage return being appended and call echo to do double %% translation.

 

Because that (md) address may have been used by other script. Using write I'm sure that it will write from the beginning and not adding to something that it's already there.

Btw, how much memory is in grub4dos, for example, between 0x220 and 0x221? Bytes or memory blocks...

 

Also, why do you need to calculate the size of the (md)0x220+xxxx device? Just use a big number that will always be more than you need.

 

:D I guess that's a "bad" habit of mine from Delphi where I had to be careful that I will not use too much RAM (MB, GB). I guess it's not a big problem here with only hundreds or thousands of bytes but, since it's easy to code this value, I used it anyway...



#16 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 28 May 2013 - 11:28 AM

You can be sure that you are at the start if you use > for the first write.

 

(md) is a memory 'device' and works in blocks (or 'sectors') of 512 bytes.

so 0x220  is 544*512/1024 = 272K in memory. If you go above 1MB or (md)0x800 then you won't need to worry about not having enough memory or running into the graphics memory buffer at 0A000:0h (md)0x500 or hitting any BIOS workspace which can be around 9c00:0h  (md)0x4e0.



#17 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 28 May 2013 - 11:53 AM

You can be sure that you are at the start if you use > for the first write.

 

Ok, now I know :)

 

(md) is a memory 'device' and works in blocks (or 'sectors') of 512 bytes.

so 0x220  is 544*512/1024 = 272K in memory. If you go above 1MB or (md)0x800 then you won't need to worry about not having enough memory or running into the graphics memory buffer at 0A000:0h (md)0x500 or hitting any BIOS workspace which can be around 9c00:0h  (md)0x4e0.

 

Ok, so using 0x200..0x300 for something small, or above 0x800 for something big.

I understand.

 

Thank you.

 

A question: does grub4dos uses some cache/buffer when reading from storage devices...? Something like that will increase the speed a bit (with slow storage devices)...



#18 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13748 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 28 May 2013 - 12:25 PM

Btw, how much memory is in grub4dos, for example, between 0x220 and 0x221? Bytes or memory blocks...
 

What do you mean?, they are blocks (sectors), each 512 bytes.
So, 0x221-0x220=1 block or 512 bytes.

:cheers:
Wonko

P.S.: Oopps, sorry, for some reason I didn't see previous reply by Steve :blush:

#19 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 28 May 2013 - 01:12 PM

memory4grub.jpg

This show the relationship between (md) and (rd) and memory locations



#20 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 28 May 2013 - 09:20 PM

memory4grub.jpg

This show the relationship between (md) and (rd) and memory locations

 

Yes, I saw it in your guide.

I understand (mostly) how those commands works but I'm not that advanced in grub4dos coding so I can use them in a script :D



#21 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 31 May 2013 - 12:06 AM

I'm curious about one thing.

When functions like "chainloader" and "kernel" encounter an error, they echo the command and write the error.
But if, in that command, some variables were used (for example %VARNAME%), the command is echoed without "translating" them.

Example:

set AAA=BBB
chainloader /%AAA%

It displays:

chainloader /%AAA%

Error 15: file not found

I don't know if this was done deliberate or not but imho it should "translate" them... Or at least there should be a grub4dos setting that will make it translate them.
What do you think about that...?



#22 steve6375

steve6375

    Platinum Member

  • Developer
  • 6629 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films,guitars
  •  
    United Kingdom

Posted 31 May 2013 - 07:44 AM

all grub4dos commands that error do not translate variables.

I can ask chenall if this could be a possible improvement...



#23 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 31 May 2013 - 09:57 AM

Ok, thank you.

I can understand why he didn't implemented this: because one of those variables could be the reason for the error and translating it could crash the error code too. But this is not happening very often + by default it should not translate them, only with a special setting. This way I think everybody will be happy :) Except chenall, because he will have to work hard to code this  :hammer:  :rolleyes:



#24 DavidB

DavidB

    Silver Member

  • Developer
  • 611 posts

Posted 31 May 2013 - 10:33 AM

Ontopic:
I just read the Wonko's answer from this thread: http://reboot.pro/to...os/#entry155427
He said:
"the alternative is "shorter":
BIOS->(possibly)grldr.mbr->grldr->menu.lst->entry chosen(translated from grub.cfg)->Debian"

Before starting my thread I was thinking at the same thing: to parse grub.cfg in a grub4dos script and "translate" grub2 commands in grub4dos commands.
The problem is that grub4dos does not have many good functions for manipulating strings, good cycles (like a "for 1 to n do") and so on.
To implement this in a script and make it work with any Linux distro is very hard work + it will take some time for the script to parse the grub.cfg file. That's why (for the moment) I gave up and came with the idea of searching directly for the boot files. The problem with this: it's restricted to a specific distro and to specific boot parameters.
Maybe I will try making a script for all Linux distro's but only if there are others interested. Making it just for me isn't worth the trouble...



#25 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 13748 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 31 May 2013 - 12:54 PM

The problem is that grub4dos does not have many good functions for manipulating strings, good cycles (like a "for 1 to n do") and so on.

Wonko also suggested you to look a bit into WENV (that has some "better" features) ;).

But really, it shouldn't be that difficult to translate "plain" GRUB2 entries into grub4dos ones (and I would rather expect the script to be run just "once per distro", i.e. it whould IMHO be a "translator" which result could be a menu.lst entry, as opposed to a "on-the-fly" or "real-time-translator", in this case even if the processing takes a bunch of seconds, it does so only once) , the real issue is that grub4dos (while having far better and more capabilities IMHO than GRUB2) misses one that is unfortunately often used nowadays by a number of distro's, the mounting of a .iso as loopback device.

 

:cheers:

Wonko







Also tagged with one or more of these keywords: linux, dynamic

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users