Jump to content











Photo
- - - - -

Effective way to determine Linux's sda/hda disks and partitions equivalents in Grub4dos

linux sda hda

  • Please log in to reply
26 replies to this topic

#1 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 15 November 2016 - 11:33 AM

Pretty much as the title says, I am wondering what is the most effective way to determine Linux's disk/partition tags from grub4dos counterparts, like for example:

  • (hd0,0) = sda1
  • (hd0,1) = sda2
  • (hd1,0) = sdb1
  • (hd1,1) = sdb2

 

The partition number is easy because it's simply the same partition number +1.

But the disk number/letter isn't so and seems to only be determinable using nested "if"s.

 

At the moment I'm using something like this:

# Determine Linux disk/partition id - set LXDSKTYP to use hd instead of sd if using IDE disk
set LXDSKTYP=sd
find --set-root /target/file.ext
if exist /target/file.ext set DSKN=%@root:~3,1% && set PRTN=%@root:~5,1%
if %DSKN%==0 set LXDSK=a || if %DSKN%==1 set LXDSK=b || if %DSKN%==2 set LXDSK=c || if %DSKN%==3 set LXDSK=d
if exist PRTN set /a LXPRTN=%PRTN%+1
if exist LXDSK set LXDSKID=%LXDSKTYP%%LXDSK%%LXPRTN%

Due to my limited knowledge of Grub4dos and it's extensive range of possibilities, I wonder if a better approach is possible, particularly for determining the disk letter.

 

Thanks for your input ;)


Edited by ner0, 15 November 2016 - 11:39 AM.


#2 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 15 November 2016 - 02:31 PM

What if you have more than 9 disks? :dubbio:

Something *like* this should do:
set string=0a1b2c3d4e5f6g
set /a offset=2*%DSKN%+1
call set LXDSK=%^string:~%offset%,1%
Is the snippet you posted part of a menu.lst entry?
IMHO it would be more appropriate to use a (grub4dos) batch for these cases, cannot say if call set and expansion works in a .lst :unsure:.

:duff:
Wonko
  • ner0 likes this

#3 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 15 November 2016 - 04:11 PM

What if you have more than 9 disks? :dubbio:

Something *like* this should do:

set string=0a1b2c3d4e5f6g
set /a offset=2*%DSKN%+1
call set LXDSK=%^string:~%offset%,1%
Is the snippet you posted part of a menu.lst entry?
IMHO it would be more appropriate to use a (grub4dos) batch for these cases, cannot say if call set and expansion works in a .lst :unsure:.

:duff:
Wonko

 


Yes, the snippet is supposed to be used in a menu lst file, and yes, probably batch would be better.
But, your example works wonderfully, genius :clap:

As for more than 9 drives, that shouldn't happen but even if it did I made a little tweak to the script:

# Determine Linux disk/partition id - set LXDSKTYP to use hd instead of sd if using IDE disk
set LXDSKTYP=sd
find --set-root /target/file.ext
if exist /target/file.ext set DSKN=%@root:~3,1% && set PRTN=%@root:~5,1%
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z
if %DSKN%<=9 set /a offset=2*%DSKN%+1
if %DSKN%>=10 set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1%
if exist PRTN set /a LXPRTN=%PRTN%+1
if exist LXDSK set LXDSKID=%LXDSKTYP%%LXDSK%%LXPRTN%

Got up to 25 26 drives covered but I suppose the sky is the limit :loleverybody:
Works great inside the lst, thanks a lot Wonko :good:


Edited by ner0, 15 November 2016 - 04:14 PM.


#4 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 15 November 2016 - 04:53 PM

That is very good :thumbsup:, but I asked about more than 9 disks, disk drives, like (hd10), (hd11) etc. (a rare case mind you), the issue here is the parsing of the (hd9,0) vs. (hd10,0) or - worse - (hd10,10)

the

 

if exist /target/file.ext set DSKN=%@root:~3,1% && set PRTN=%@root:~5,1%

will get you just 1 character/digit (and not necessarily the "right" one(s)).

 

About the batch file vs. menu.lst, it is years that I try to convince people that menu.lst should be simple (and fail miserably at it :(), the other thing that I completely fail to convey is that the n in (hdm,n) is a volume (what gets a drive letter in windows) and    m   is the disk (or physical drive, i.e. the whole thing).

 

Your variable DSKN PRTN should be VOLN (or DRVN) to avoid the above (common, rest assured) confusion.    :whistling:

 

:duff:

Wonko

 

Edit: corrected error, what I meant is that a partition is a volume if it is Primary and "a suffusion of yellow" if it is Extended, my bad :(



#5 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 15 November 2016 - 07:10 PM

Oh yeah, I completely forgot about the variables up there, I'll solve that later (for disks and partitions) when I have some spare time and post back.

 

And batch vs menu.lst, could you give me some pointers about what is what?

I know batch pretty well, that is I'm used to scripting in batch often so I could see an advantage for me there.

But isn't batch scripting embedded in menu.lst all the same? Do you have some beginner's guide for batch in grub4dos so that I could get up to speed?

 

As for the the distinction you're making in (hdx,y), I know that x is the disk and y is the partition/volume.

But you seem to contradict yourself in there, you say that n (y) is a volume and m (x) is the disk, which we can all agree upon... but then you say that my variable for disk should be named volume, why? Are you sure it isn't you that is reading into it incorrectly?

In (hdx,y)%@root:~3,1(DSKN) is x and %@root:~5,1(PRTN) is y.

 

To clarify, my DSKN variable is correctly assigned as the x (m) meaning disk/drive (hence DSK), and PRTN variable is correctly assigned as the y (n) meaning partition/volume (hence PRT).



#6 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 15 November 2016 - 07:20 PM

My bad :(
I meant PRTN should be VOLN or DRVN, a partition can be extended (and it will get a "name" in Linux depending on the actual partition slot occupied by it, but not *anything* in Windows or in grub4dos, though as an example partnew command of grub4dos will use the partition table slot number - like linux).
Correcting my previous post to avoid the issue.
If you have a disk partitioned like here:
http://linuxbsdos.co...tions-in-linux/
http://www.linuxbsdo...ons-600x465.png

3partitions-600x465.png
you will have nothing corresponding to sda4 or sdc2 in Windows or in grub4dos.

About batch, there is very scarce documentation, look on rmprepusb site for some examples (and tips) the language is very similar to Windows batch, though there are some differences.
Also if you search for "[Release]" in Titles on reboot.pro, you will find a few examples by me (shameless plug) using also WENV (which makes the language very similar to Windows batch).
The only person actually knowing fully the grub4dos batch language is probably Chenall, but looking for examples of scripts on his site is a royal PITA as the site is mostly in Chinese and also the scripts are often half in Chinese

:duff:
Wonko



#7 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 15 November 2016 - 09:59 PM

The distinction between partition and volume is somewhat fuzzy, but I assume you're right and volume is more accurate of a description.

In any case, here is the final script:

# Determine Linux disk/volume id - set LXDSKTYP to use hd instead of sd if using IDE disk
set LXDSKTYP=sd
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z
find --set-root /target/file.ext
if exist %@root%/target/file.ext set DSKN=%@root:~3,2% && set VOLN=%@root:~6,2%
if "%DSKN:~-1%"=="," set DSKN=%DSKN:~0,1% && set VOLN=%root:~5,2%
if "%VOLN:~-1%"==")" set VOLN=%VOLN:~0,1%
if %DSKN%<=9 set /a offset=2*%DSKN%+1
if %DSKN%>=10 set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1%
if exist VOLN set /a LXVOLN=%VOLN%+1
if exist LXDSK set LXVOLID=%LXDSKTYP%%LXDSK%%LXVOLN%

Thanks for the help!



#8 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 16 November 2016 - 09:36 AM

Sure the distinction is fuzzy, and wait until you read this ;):

http://reboot.pro/to...e-6#entry123056

 

Good work :) with the little script, though I am not convinced it will work in all possible cases (withing 99 disks and 99 :w00t: volumes).

Have you tested it "cold" (i.e. without verifying the existence of /target/file.ext ) in these cases :unsure::
(hd0,0)

(hd10,1)

(hd2,11)

(hd12,13)

 

I have not handy a suitable grub4dos test environment, but *something like* this:

if "%@root:~4,1%"=="," set DSKN=%@root:~3,1% && set VOLN=%@root:~5,-1%
if "%@root:~5,1%"=="," set DSKN=%@root:~3,2% && set VOLN=%@root:~6,-1%

should do ...

and could even possibly be "simplified" in fewer commands and removing a couple of if's :dubbio::
if "%@root:~4,1%"=="," set DSKN=%@root:~3,1% && set /a VOLN=%@root:~5,-1%+1 && set /a offset=2*%DSKN%+1

if "%@root:~5,1%"=="," set DSKN=%@root:~3,2% && set /a VOLN=%@root:~6,-1%+1 && set /a offset=2*%DSKN%+%DSKN%-10+2

maybe you need a "call set" to have DSKN expanded in the last set /a ...

 

:duff:

Wonko



#9 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 16 November 2016 - 10:42 AM

Well, obviously that as is it won't work past disk z or 26th.
It could be made to, but seems pointless.

As for working in all 4 cases:
- 1 digit disk, 1 digit volume
- 2 digit disk, 1 digit volume
- 1 digit disk, 2 digit volume
- 2 digit disk, 2 digit volume

I had tested it with an hardcoded variable and it works for all cases, as does your suggestion above, which is a bit prettier but is one 'and' longer that it needs to be in comparison to mine. As for your second suggestion, it indeed needs a call on the offset variable, but unfortunately it won't work properly for whatever reason. Well, it works but it only works if run twice, for example:

run #1

set root=(hd0,0)
...
echo %LXVOLID%
sda1

run #2

set root=(hd1,1)
...
echo %LXVOLID%
sda2

run #3

set root=(hd1,2)
...
echo %LXVOLID%
sdb3

run #2 didn't update the disk letter set by 'offset' variable, only did so at the next run.

So, it unfortunately seems that the script cannot be improved in the way described, which is a shame because it would have spared at least 2 lines/ifs.


Edited by ner0, 16 November 2016 - 10:44 AM.


#10 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 16 November 2016 - 11:37 AM

Okay, so the problem was that I should have been using "&;" instead of "&&" to refresh variable's values.

At this point both scripts work with a few less lines. I gave up on checking if the destination file exists because there is not point in it, if the file (root) does not exist then the rest of the script would fail either way.

# Determine Linux disk/volume id - set LXDSKTYP to use hd instead of sd if using IDE disk
set LXDSKTYP=sd
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z
find --set-root /target/file.ext &; set DSKN=%@root:~3,2% && set VOLN=%@root:~6,2%
if "%DSKN:~-1%"=="," set DSKN=%DSKN:~0,1% && set VOLN=%@root:~5,2% &; if "%VOLN:~-1%"==")" set VOLN=%VOLN:~0,1%
if %DSKN%<=9 set /a offset=2*%DSKN%+1 || if %DSKN%>=10 set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1% && set /a LXVOLN=%VOLN%+1 &; set LXVOLID=%LXDSKTYP%%LXDSK%%LXVOLN%
# Determine Linux disk/volume id - set LXDSKTYP to use hd instead of sd if using IDE disk
set LXDSKTYP=sd
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z
find --set-root /target/file.ext
if "%@root:~4,1%"=="," set DSKN=%@root:~3,1% && set /a VOLN=%@root:~5,-1%+1 &; call set /a offset=2*%DSKN%+1
if "%@root:~5,1%"=="," set DSKN=%@root:~3,2% && set /a VOLN=%@root:~6,-1%+1 &; call set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1% &; set LXVOLID=%LXDSKTYP%%LXDSK%%VOLN%

I'm still doing some tests but it looks good


Edited by ner0, 16 November 2016 - 12:00 PM.


#11 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 16 November 2016 - 12:15 PM

This can now be used, for example, with a script by steve6375, from (CloneZillaBackup.zip) here: http://www.rmprepusb...ials/clonezilla

 

The script from that tutorial uses a static mapping, like this:

# find source volume for Windows and our backup volume - use hda instead of sda if IDE HDD
if exist (hd0,0)/windows/explorer.exe set WDRV=sda1
if exist (hd0,1)/windows/explorer.exe set WDRV=sda2
if exist (hd0,2)/windows/explorer.exe set WDRV=sda3
if exist (hd0,3)/windows/explorer.exe set WDRV=sda4
if exist (hd0,0)/clonezilla/live/vmlinuz set BAKDRV=sda1
if exist (hd0,1)/clonezilla/live/vmlinuz set BAKDRV=sda2
if exist (hd0,2)/clonezilla/live/vmlinuz set BAKDRV=sda3
if exist (hd0,3)/clonezilla/live/vmlinuz set BAKDRV=sda4
if exist (hd0,4)/clonezilla/live/vmlinuz set BAKDRV=sda5
if exist (hd0,5)/clonezilla/live/vmlinuz set BAKDRV=sda6
if exist (hd0,6)/clonezilla/live/vmlinuz set BAKDRV=sda7
if exist (hd1,0)/clonezilla/live/vmlinuz set BAKDRV=sdb1
if exist (hd1,1)/clonezilla/live/vmlinuz set BAKDRV=sdb2
if exist (hd1,2)/clonezilla/live/vmlinuz set BAKDRV=sdb3
if exist (hd1,3)/clonezilla/live/vmlinuz set BAKDRV=sdb4
if exist (hd1,4)/clonezilla/live/vmlinuz set BAKDRV=sdb5
if exist (hd1,5)/clonezilla/live/vmlinuz set BAKDRV=sdb6
if exist (hd1,6)/clonezilla/live/vmlinuz set BAKDRV=sdb7
if exist (hd2,0)/clonezilla/live/vmlinuz set BAKDRV=sdc1
if exist (hd2,1)/clonezilla/live/vmlinuz set BAKDRV=sdc2
if exist (hd2,2)/clonezilla/live/vmlinuz set BAKDRV=sdc3
if exist (hd2,3)/clonezilla/live/vmlinuz set BAKDRV=sdc4
if exist (hd2,4)/clonezilla/live/vmlinuz set BAKDRV=sdc5
if exist (hd2,5)/clonezilla/live/vmlinuz set BAKDRV=sdc6
if exist (hd2,6)/clonezilla/live/vmlinuz set BAKDRV=sdc7
if exist (hd3,0)/clonezilla/live/vmlinuz set BAKDRV=sdd1
if exist (hd3,1)/clonezilla/live/vmlinuz set BAKDRV=sdd2
if exist (hd3,2)/clonezilla/live/vmlinuz set BAKDRV=sdd3
if exist (hd3,3)/clonezilla/live/vmlinuz set BAKDRV=sdd4
if exist (hd3,4)/clonezilla/live/vmlinuz set BAKDRV=sdd5
if exist (hd3,5)/clonezilla/live/vmlinuz set BAKDRV=sdd6
if exist (hd3,6)/clonezilla/live/vmlinuz set BAKDRV=sdd7

It can now be reduced to this:

# find source volume for Windows and our backup volume - use hda instead of sda if IDE HDD
set LXDSKTYP=sd
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z
find --set-root /windows/explorer.exe
if "%@root:~4,1%"=="," set DSKN=%@root:~3,1% && set /a VOLN=%@root:~5,-1%+1 &; call set /a offset=2*%DSKN%+1
if "%@root:~5,1%"=="," set DSKN=%@root:~3,2% && set /a VOLN=%@root:~6,-1%+1 &; call set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1% &; set WDRV=%LXDSKTYP%%LXDSK%%VOLN%
find --set-root /clonezilla/live/vmlinuz
if "%@root:~4,1%"=="," set DSKN=%@root:~3,1% && set /a VOLN=%@root:~5,-1%+1 &; call set /a offset=2*%DSKN%+1
if "%@root:~5,1%"=="," set DSKN=%@root:~3,2% && set /a VOLN=%@root:~6,-1%+1 &; call set /a offset=2*%DSKN%+%DSKN%-10+2
call set LXDSK=%^string:~%offset%,1% &; set BAKDRV=%LXDSKTYP%%LXDSK%%VOLN%

Edited by ner0, 16 November 2016 - 12:16 PM.


#12 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 16 November 2016 - 12:43 PM

Very good!  :1st:
To be picky (as I am, BTW), given that the formula:
set /a offset=2*%DSKN%+1
is genrically of the "ax+b" type, I would prefer:
set /a offset=2*%DSKN%+%DSKN%-10+2
as:
set /a offset=3*%DSKN%-8
;)
 
Now, for no apparent reason, the same in grub4dos batch (to be tested/verified):
!BAT
debug 0
if "%1"=="" goto :error1
setlocal
set target=%1
if "%target%"=="/?" goto :syntax
if "%target%"=="-help" goto :syntax
set LXDSKTYP=sd
set string=0a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z

if "%target:~4,1%"=="," call :parse 1 5 2 +1
if "%target:~5,1%"=="," call :parse 2 6 3 -8


call set LXDSK=%^string:~%offset%%,1%
set LXVOLID=%LXDSKTYP%%%LXDSK%%%VOLN%
set LXVOLID
endlocal && set LXVOLID=%LXVOLID%
goto :EOF

:parse
# %1 is length of disk number
# %2 is offset of volume number
# %3 is string offset multiplier
# %4 is string offset delta
set DSKN=%target:~3,%1%
set /a VOLN=%target:~%2,-1%+1
set /a offset=%3*%DSKN% %4
goto :EOF


:error1
echo Missing or invalid parameter
echo you must provide an EXISTING target volume
echo such as (hd0,0), (hd1,10), etc.
echo. 
goto :syntax
goto :EOF

:syntax
echo *lxvolid.g4b* - grub4dos BAT! file by jaclaz
echo released under the jaclaz's CAREWARE license
echo Version 0.01 Alpha, from an idea by Ner0
echo.
echo syntax:
echo lxvolid.g4b <volume in grub4dos notation>
echo examples:
echo lxvolid.g4b (hd0,0)
echo lxvolid.g4b (hd12,9)
echo .
echo Echoes and sets the LXVOLID variable to the Linux
echo SD corresponding device, i.e. sda1, sdm9, etc.
goto :EOF
This (or *something* like it) would amount to one line in the menu.lst.
 
 
:duff:
Wonko
  • ner0 likes this

#13 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 16 November 2016 - 02:19 PM

Batch also works great, although it doesn't seem to support comments with 'rem', it should use either '::' or '#'.

Also, the empty line isn't working with either "echo." or "echo ."


Edited by ner0, 16 November 2016 - 02:45 PM.


#14 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 16 November 2016 - 03:29 PM

Batch also works great, although it doesn't seem to support comments with 'rem', it should use either '::' or '#'.
Also, the empty line isn't working with either "echo." or "echo ."

Thanks, corrected.

:duff:
Wonko

#15 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 16 November 2016 - 05:05 PM

Here is a more grub4dosish :w00t: version (managed access to a VM with a grub4dos):

!BAT
#abcdefghijklmnopqrstuvwxyz
setlocal
set DSKN=%1
echo %DSKN:~3,-1% > (md)0x3000+1
cat --locate=, --replace=" "  (md)0x3000+1
cat --length=10 (md)0x3000+1 | set string=
call :parse %string%
cat --length=1 --skip=%DSKN% %~dpnx0 | set DSKN=
set LXVOLID=sd%DSKN%%%VOLN%
echo %1=%LXVOLID%
endlocal && set LXVOLID=%LXVOLID%
goto :eof

:parse
set /a DSKN=%1+7
set /a VOLN=%2+1
goto :eof

:duff:

Wonko


  • ner0 likes this

#16 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 16 November 2016 - 06:44 PM

Nice, but I don't understand how this one works.

Besides the very ingenious approach, I'm confused about how the (commented) alphabetical string is taken into account.

 

Here is what I can gather, assuming that the disk/volume is (hd10,11):

- (md)0x3000+1 ends up with "10 11" and that values is passed on to %string%.

- Then :parse is called using the arguments 1 and 2 (values 10 and 11) from %string%.

- DSKN ends up with value 17 (10+7).

- VOLN ends up with value 12 (11+1).

- Here is the tricky part for me, my interpretation of that last 'cat' is: "obtain 1 character in length, starting at position 17th in %~dpnx0"

 

Now, %~dpnx0 is the full path, filename and extension of the script itself, and this is where the script will read the alphabetical string.

!BAT -> 4 characters

# -> 1 character

 

Yet it has to skip 7 characters, is it because of <CR><LF> taking 2 additional characters?  :dubbio:

 

Would you mind enlightening me?



#17 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 16 November 2016 - 06:59 PM

Yep :).

Provided that the batch is named mytest.g4b, try:

cat --hex  --length=8 /mytest.g4b

This:

cat  --locate=# /mytest.g4b

returns 6 (the "!BAT" 4 + CR and LF 2) so "a" is at offset 7.

 

:duff:

Wonko

 

P.S.: and here is another batch, fresh from today, by Mythenadia:
http://reboot.pro/to...nux-equivalent/



#18 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 17 November 2016 - 07:37 PM

A one-liner (almost), thanks to the approach by Mythenadia and to ascii :w00t: :

!BAT
set /a vol=*0x829e&0xffff+1 > nul && calc *0x82a0&0x1f+97 | call Fn.2 | set LXVOLID=sd &;  call set LXVOLID=%LXVOLID%%%vol%
set LXVOLID

Should work also in menu.lst, if the %%% are reduced to two:

set /a vol=*0x829e&0xffff+1 > nul && calc *0x82a0&0x1f+97 | call Fn.2 | set LXVOLID=sd &; call set LXVOLID=%LXVOLID%%vol%

:duff:

Wonko


  • ner0 likes this

#19 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 17 November 2016 - 08:30 PM

Wow, never thought it could get much shorter that what we already had.

And thinking we started from scratch...  :1st:

 

For those interested from where a portion of this last approach came from: http://reboot.pro/to...nux-equivalent/


Edited by ner0, 17 November 2016 - 08:39 PM.


#20 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 17 November 2016 - 09:42 PM

I feel the need to try and make sense of this. :dubbio:

 

Getting the volume number

*0x829e&0xffff+1

0x829e is the memory address where the (hex) volume number for the current root is located, ex: 0x8000001

0xffff seems to work as a mask which pulls the resulting hex characters from right to left, in this case the 4 rightmost characters (0001), leading zeroes being ignored.

+1 adds 1 to the decimal result from the previous two combinations.

 

 

Getting the disk number

calc *0x82a0&0x1f+97

calc is a command that allows to do basic arithmetic operations

0x82a is the memory address where the (hex) disk number for the current root is located, ex: 0x80

0x1f seems to work as a mask which pulls the resulting hex characters from right to left, in this case the rightmost character (0), but I'm not sure why 0x1f and not just 0xf

+97 the decimal number 97 is the ASCII equivalent to the letter 'a', and so whatever the disk number is, 97 will be added to it so that it later returns the corresponding letter (0=a, 1=b, 2=c, etc).

 

 

Getting the disk letter

call Fn.2 | set LXVOLID=sd

call Fn.2 calls an internal function, Fn.2, documented as putchar, which will convert a decimal number, obtained in the last step, to it's ASCII equivalent (0+97=a, 1+97=b, 2+97=c).

| set LXVOLID=sd the | symbol seems to work in such a way that the result from the previous operation is appended to the end of the next, in this case it adds the letter 'a' to the variable LXVOLID, which already holds 'sd', resulting in 'sda'.

 

 

Extensive documentation on internal variables and functions can be found here: http://www.rmprepusb...s-and-functions

 

 

I think that what I'm really grasping at is understanding properly how the "masks" work, I'm assuming but do not really know why 0x829e&0xffff or 0x82a0&0x1f

 

Also, why the leading asterisk?


Edited by ner0, 17 November 2016 - 09:59 PM.


#21 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 18 November 2016 - 11:49 AM

The leading asterisk means (in this context) that it is an address in memory.

I.e. 0x829e is the hex value, decimal 33438, *0x829e is the value at address 0x829e.

 

You can use read to check values in memory (without asterisk):

Example:

root (hd0,0)

read 0x829e -> 0x800000

read 0x82a0 -> 0x80

root (hd1,1)

read 0x829e -> 0x810001

read 0x82a0 -> 0x81

root (hd3,2)

read 0x829e -> 0x830002

read 0x82a0 -> 0x83

The first location is a 3 byte "field", the second is a single byte one (this is how grub4dos is made, the other bytes are always set to 0), first is disk and volume, second is just disk.

 

BIOS (and DOS, and grub4dos internally) number disks starting from 0x80, i.e. first hard disk is disk 128, second is 129, etc (you will find this kind of notation in several good ol' DOS tools) disks are (hd0) to (hd31) or 0x80 to 0x9f or 128 to 159.

By "&ing" (which is the AND binary operation) with the suitable complement you obtain the "net" number,

calc 0x83&0x1f means 131 AND 31, i.e. 10000011 AND 00011111, calc 0x830002&0xffffff means 100000110000000000000010 AND 1111111111111111:

10000011

00011111

-------------

00000011 -> 3

 

100000110000000000000010

000000001111111111111111

--------------------------------------

000000000000000000000010 ->2

 

Now, you can replace:

calc *0x82a0&0x1f -> 3

With:

calc *0x82a0-0x80 or calc *0x82a0-128, both will result in 3 but

you cannot easily do the same for calc *0x829e&0xffff

you could do:

calc -65536**0x82a0+*0x829e or calc -0x10000**0x82a0+*0x829e, both will result in 2, but not really "elegant" :unsure:.

 

:duff:

Wonko



#22 ner0

ner0

    Member

  • Advanced user
  • 83 posts

Posted 18 November 2016 - 12:05 PM

Thanks for the detailed explanation.



#23 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 20 November 2016 - 03:13 PM

I would say "final":
 
!BAT
calc *0x82a0-31 | call Fn.2 | set LXVOLID=sd &;  calc *0x829e&255+1 > nul &; set LXVOLID=%LXVOLID%%%@retval%
set LXVOLID
calc *0x82a0-31 | call Fn.2 | set LXVOLID=sd &;  calc *0x829e&255+1 > nul &; set LXVOLID=%LXVOLID%%@retval%
a little shorter and avoiding the use of  the "vol" variable.
 
:duff:
Wonko
  • ner0 likes this

#24 steve6375

steve6375

    Platinum Member

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

Posted 10 January 2017 - 10:04 PM

If there are 3 internal hard disks and one USB drive connected and we need to get the USB drive device = sdd, we need to get the last device.

 

This assumes that the boot volume is the current root... We could use find --set-root at line 2.

debug 1 ;; rootnoverify (hd-1) > nul ;; calc *0x82a0-31 | call Fn.2 | set LXVOLID=sd
root (bd) > nul ;; calc *0x829e&255+1 > nul &; set LXVOLID=%LXVOLID%%@retval%
echo
echo USB drive is detected as %LXVOLID%

debug must not be off (0) or it won't work.

If there are more than one USB drives connected (or card reader??) this may not work correctly



#25 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 11 January 2017 - 10:51 AM

debug must not be off (0) or it won't work.

If there are more than one USB drives connected (or card reader??) this may not work correctly

Yep, and there is additionally some possible issues with the way the BIOS behaves. :(

 

The debug note is useful for those that fiddle with it, at boot time debug is normally 1, in theory it should be the responsibility of the *whatever* changes its default level to 0 or off to restore it.

 

Almost incredibly :w00t: :ph34r: an useful reference is coming from an old DELL document:

http://www.dell.com/...0392-Domsch.pdf

 

Passing to Linux kernels UUID or LABEL information for root= would be more reliable, but as we have seen here:
http://reboot.pro/to...rom-vhd-how-to/

there may be other issues that depend on the specific distro.

 

:duff:

Wonko







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

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users