Jump to content











Photo
- - - - -

Writing to the Grub4dos' keyboard buffer possible?

grub4dos

  • Please log in to reply
85 replies to this topic

#76 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted 2 weeks ago

The board is set for giving limited capabilities to posters will less than 50 posts (this is because of spammers editing previous posts to add links to crappy sites), you are near to reach that number of posts, from then on you will have no more time limits on editing previous posts.

Thanks a lot, now this is clear to me.

 

The %* is ALL parameters excluded the %0 one.

 

In batch you have the shift command to manipulate parameter numbers/order, but the grub4dos implementation does not accept shift -1 if I recall correctly (not that it is usually needed).

Good to know about %*.

 

What I do not like so much about using shift in the main routine is losing arguments (with regard to in this 'function'-project). And if there are many arguments, it is a waste of variables, needed to hold the values of the arguments.

 

In one of my projects I was because of this *thing* condemned to endless debugging with varsleft.g4b (I believe it's from steve6375 - no author 'inside'. It's a very handy debugging-tool).

 

I experimented with call :%1 %* - seems to give no problems, I only have to test if shift inside a sub-routine does the same, without losing anything in the main routine.

 

I have been thinking about the dll-'idea' I should 'not attribute' to you.

To give this sort of call's a more unified structure, should their not be error-handling too? Although I have only vague notions of, for instance, the windows API, I know many different error-codes are needed.

 

To exemplify I made a function I really need: counting number of labels. My latest count (105 labels) took me a very long time, and I was not even sure about the final number. So I made the function 'cntlabel'. Still not very high-level, just meant to give an idea about a possible general structure.

!BAT
#FUNCTION.G4B by deomsh; thanks to Wonko the Sane
#DLL for Grub4Dos
#Arguments: function, mandatory arguments, optional arguments; errormsg: 0=No function given, 1=Function not supported
#Implemented: cntlabel (20210717)
debug off
setlocal && set *
if "%~1"=="" && set /a errormsg=0 > nul
if not exist errormsg && call :dbfunc %~1
if not exist errormsg && call :%~1 %*
endlocal && set result=%result% && set errormsg=%errormsg%
echo %1: result=%result% errormsg=%errormsg%
goto :eof

:cntlabel #Function: count number of labels; Argument: FILE; Optional: dos or mac; errormsg: 2=FILE not given, 3=FILE does not exist
setlocal && set *
if "%~2"=="" && endlocal && set /a errormsg=2 > nul && goto :eof
if not exist %~2 && endlocal && set /a errormsg=3 > nul && goto :eof
if /i "%~3"=="dos" && set EOL=\x0D\x0A ! set EOL=\x0A
if /i "%~3"=="mac" && set EOL=\x0D
echo EOL=%EOL%
cat --locate=%EOL%\x3A %~2 > nul &; set /a result=%@retval% > nul
endlocal && set result=%result%
goto :eof

:dbfunc #database of available functions
setlocal && set *
if not /i %~1==cntlabel && endlocal && set /a errormsg=1 > nul && goto :eof
endlocal
goto :eof

This is the 'print-screen' of the output (the optional argument gives also more possible uses of cntlabel):

grub> (hd0,0)/function.g4b
: result: errormsg=0 
grub> (hd0,00/function.g4b cntlabe 
cntlabe: result= errormsg=1 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4d
cntlabel: result= errormsg=3 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b 
EOL=\x0A 
cntlabel: result=102 errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b dos 
EOL=\x0D0A 
cntlabel: result=102 errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b mac 
EOL=\X0D 
cntlabel: result= errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b ms-dos 
EOL=\0Ax 
cntlabel: result=102 errormsg= 
grub>

BTW I tried to make textual error messages too, but today I was plagued again by Error 16 Inconsistent filesystem structure. Has something to do with editing files in Windows in combination with Imdisk to have access to VBox in combination with 'saving' grub4dos-sessions in VBox. After 'refreshing everything' Error 16 disappeared.

 

What do you think about error-handling?
 



#77 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted 2 weeks ago

Edit 'print-screen':

OCR was bad this time, my eyes too. The echo of the three last EOL-codes should have been the following ones:

EOL=\x0D\x0A

EOL=\x0D

EOL=\x0A

Edited by deomsh, 2 weeks ago.


#78 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 2 weeks ago

Every time you use call or invoke a file with parameters, it is a different stack of % parameters.

Using shift in "main" will shift the "main" ones, if you use shift in a subroutine it will shift the "call" parameters.

No problem there.

 

About error checking/handling, it could be a nice feature, but (IMHO) not needed and actually overkill in the specific case of "dividing" a large batch in a "main program"+"functions library".

 

I mean - unlke the mathfunc.g4b (lousy) example, the idea of a .lll file is that it is "never" called from command line, but only by programs, so it is the program Author that is responsible for calling the library (rectius the function in it) with the correct parameters.

 

If the idea is that of using these functions from command line, it would still make sense to have an intermediate level (not entirely unlike the rundll32.exe) that takes care of validating the user input/parameters and echo result(s) in a suitable format.

 

:duff:

Wonko


  • deomsh likes this

#79 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted 4 days ago

@Wonko
I played a bit with your (?) idea of 'Loosely Linked Libraries' and I 'found' following structure.

Because with call :%1 %* it is possible to link to other .LLL-files, I think it could be useful, from a developmental perspective, to split the FUNCTION-file you envisioned in 'Implemented' and 'Linked' functions. The 'Linked' functions can be still in development, while the 'Implemented' functions are (more or less) 'ready'. Also the .LLL-files have the same structure, so can be tested from the command-line too (Grub4Dos doesn't care, as long !BAT is on the first line). After finishing a 'Linked' function, all that has to be done is copying the call-part to the main FUNCTION.G4B. For example I found my function 'CntLabel' counted '::' at the beginning of a line too, so already a (small) revision was needed (I always use # before a comment).

Below the structure of the general file FUNCTION.G4B and as an example MAKEUUID.LLL (echos should be commented out later).

!BAT
#FUNCTION.G4B v0.1.5 by deomsh, based on idea of Wonko the Sane
#DLL for Grub4Dos (version: from 2019)
#Arguments: Function, Mandatory Arguments, Optional Arguments
#Implemented: CntLabel; CntLine;
#Linked to .lll-file: CopyFile; IsMaxLen; ParseArg; ParseCmd; MakeUuid
debug status > nul ;; set debugsts=%@retval% ;; debug 0
echo %*
call :%~1 %*
echo Function: %1 result=%result%
debug %debugsts%
set debugsts=
goto :eof

:CopyFile
call CopyFile.lll %*
goto :eof

:IsMaxLen
call IsMaxLen.lll %*
goto :eof

:ParseArg
call ParseArg.lll %*
goto :eof

:ParseCmd
call ParseCmd.lll %*
goto :eof

:MakeUuid
call MakeUuid.lll %*
goto :eof

:CntLabel
#Function: count number of labels; Argument: FILE; Optional: dos or mac
setlocal && set *
set file=%~2 &; if "%file:~0,4%"=="(md)" && set FILE=%~dnx2 ! set FILE=%~dpnx2
if /i "%~3"=="dos" && set EOL=\x0D\x0A ! set EOL=\x0A
if /i "%~3"=="mac" && set EOL=\x0D
cat --locate=%EOL%\x3A %FILE% > nul &; set /a count1=%@retval% > nul
cat --locate=%EOL%\x3A\x3A %FILE% > nul &; set /a count2=%@retval% > nul
set /a result=%count1% > nul && if exist count2 && set /a result=%count1%-%count2% > nul
endlocal && set result=%result%
goto :eof

:CntLine
#Count lines in textfile; Argument: FILE; Optional: dos|unix|mac; Default: dos
setlocal && set *
set file=%~2 &; if "%file:~0,4%"=="(md)" && set FILE=%~dnx2 ! set FILE=%~dpnx2
if /i not "%~3"=="" if /i not "%~3"=="dos" || set EOL=\x0D\x0A &; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="dos" && set EOL=\x0D\x0A &; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="unix" && set EOL=\x0A &; cat --locate=\x0D %FILE% > nul |; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="mac" && set EOL=\x0D &; cat --locate=\x0A %FILE% > nul |; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if not exist result && set /a result=0 > nul
endlocal && set result=%result%
goto :eof

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A basemd=%~2 > nul
set /A memrange=%~3 > nul
set /A skipmem=%~4 > nul
set /A "basemd=%basemd% * 0x200 + %skipmem%" > nul
set /A "memrange=%memrange% * 0x200 - %skipmem%" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

!BAT
#MAKEUUID.LLL v0.1 (20210727), by deomsh. Based on unpublished VOLUUID.G4B (20200615)
#Generate MS-DOS Volume Serial Number
#Mandarory Argument: MakeUuid
echo %*
call :%~1
echo Function: %~1 result=%result%
goto :eof

:MakeUuid
setlocal && set *
#debug 0
set date=%@date%
set /a year=%date:~0,4% > nul
set /a month=%date:~5,2% > nul
set /a day=%date:~8,2% > nul
#echo date: %day%-%month%-%year% 
set time=%@time%
set /a hour=%time:~0,2% > nul
set /a minute=%time:~3,2% > nul
set /a second=%time:~6,2% > nul
set /a minute=%time:~3,2% > nul
#set /a smallsec= > nul
#echo time: %hour%:%minute%:%second%:%smallsec%
if not exist smallsec && set /a random=%@random% > nul ! set /a random=%smallsec% > nul
#echo random: %random%
if %random%>=100 && set /A smallsec=%random% / 10 > nul
if %random%>=1000 && set /A smallsec=%random% / 100 > nul
if %random%>=10000 && set /A smallsec=%random% / 1000 > nul
set /A month=%date:~5,2% * 0x100  > nul
set /A second=%time:~6,2% * 0x100 > nul
#echo month: %month% day: %day% second: %second% smallsec: %smallsec%
set /A uuidlow=%month% + %day% + %second% + %smallsec% > nul
set /a llow=%@retval% > nul
#echo llow: %llow%
#echo uuidlow: %uuidlow%
set /A hour=%time:~0,2% * 0x100 > nul
#echo hour: %hour% minute: %minute% year: %year%
set /A uuidhigh=%hour% + %minute% + %year% > nul
set /a lhigh=%@retval% > nul
#echo lhigh: %lhigh%
#echo uuidhigh: %uuidhigh%
echo Volume Serial Number: %uuidlow:~2,4%-%uuidhigh:~2,4% 
if %lhigh%==6 && if %llow%==6 && set volumeid=x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul
if %lhigh%==6 && if %llow%==5 && set volumeid=x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul
if %lhigh%==5 && if %llow%==6 && set volumeid=x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul
if %lhigh%==5 && if %llow%==5 && set volumeid=x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul
#echo Volume Serial Number little-endian: \%volumeid% (write (md)-ready)
#echo Volume Serial Number big-endian: %uuidlow:~2,4%%%uuidhigh:~2,4%
#endlocal && set volumeid=%volumeid%
endlocal && set result=%volumeid%
goto :eof

BTW Use of the .G4B-extension for FUNCTION.G4B seems more 'universal' to me (in case of use of command --set-ext=.g4b in MENU.LST).

 

BTW2 Central use of setlocal/ endlocal doesn't seem flexible enough to me if more than one variable, or an unknown number of variables is returned.

BTW3 Calling such batch-files by accident (without %1 = Function) seems 'safe' to me, nothing has been changed (in case of FUNCTION.G4B unless variable debugsts is used before - may be better not centralized too?).

What bothers me is the question of 'Memory Management'.

If a function needs working memory, I wonder if it would be better to use the main routine allocating memory to a function (with an optional argument), or use (a set of) fixed memory-addresses for all functions (which the main routine shouldn't use)?


Edited by deomsh, 4 days ago.


#80 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 4 days ago

It seems nice to me. :)

 

Though (if the idea is to save memory/variables) you don't really-really need to assign all variables, unless you need in the formula to parse the values.

I.e.:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A basemd=%~2 > nul
set /A memrange=%~3 > nul
set /A skipmem=%~4 > nul
set /A "basemd=%basemd% * 0x200 + %skipmem%" > nul
set /A "memrange=%memrange% * 0x200 - %skipmem%" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

could well be:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A "basemd=%~2 * 0x200 + %~4" > nul
set /A "memrange=%~3 * 0x200 - %~4" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

Three variable assignments removed, not noticeable at all, particularly because the function will be run once or very rarely, still, as a general rule using as much as possible the call parameters reduces usage of variables ...

 

As a side-note/OT question, the UUID generator uses the officially unofficial DOS algorithms, doesn't it? :unsure:

 

https://msfn.org/boa...&comment=980297

 

https://msfn.org/boa...#comment-987748

 

A couple small nitpicks (at first sight)  in:

 

#echo date: %day%-%month%-%year%
set time=%@time%
set /a hour=%time:~0,2% > nul
set /a minute=%time:~3,2% > nul
set /a second=%time:~6,2% > nul
set /a minute=%time:~3,2% > nul
#set /a smallsec= > nul
#echo time: %hour%:%minute%:%second%:%smallsec%
if not exist smallsec && set /a random=%@random% > nul ! set /a random=%smallsec% > nul
#echo random: %random%
if %random%>=100 && set /A smallsec=%random% / 10 > nul
if %random%>=1000 && set /A smallsec=%random% / 100 > nul
if %random%>=10000 && set /A smallsec=%random% / 1000 > nul

 

 

#1 You have duplicated the minute assignment, probably a copy/paste effect :unsure:

#2 I am not too convinced of the formula for reducing the random value into a 0<=x<=99 range  :dubbio: I have to think about it ...

 

:duff:

Wonko

 

P.S.: No, I confirm, dividing by 10/100/1000 doesn't give "random enough" results, you'd better get two digits, i.e. *something like*:

set smallsec=%@random::~-2%

or (to avoid possible leading 0, and get an actual numeric value)

set /a smallsec=1%@random::~-2%-100

or

set /a smallsec=1%@random::~-1%1%@random::~-1%-100



#81 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted 3 days ago

It seems nice to me. :)

 

Though (if the idea is to save memory/variables) you don't really-really need to assign all variables, unless you need in the formula to parse the values.

I.e.:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A basemd=%~2 > nul
set /A memrange=%~3 > nul
set /A skipmem=%~4 > nul
set /A "basemd=%basemd% * 0x200 + %skipmem%" > nul
set /A "memrange=%memrange% * 0x200 - %skipmem%" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

could well be:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A "basemd=%~2 * 0x200 + %~4" > nul
set /A "memrange=%~3 * 0x200 - %~4" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

Three variable assignments removed, not noticeable at all, particularly because the function will be run once or very rarely, still, as a general rule using as much as possible the call parameters reduces usage of variables ...

Thanks, good idea in case of %~2 and %~3. I agree 'things' should be easiest as possible (at least 'in the end').

But NOT good in case of %~4, because %~4 is an optional argument (to clean only from a given memory address, located above or below a 512 byte sector-border). The calculation is not working if %~4 is not defined, so set /A skipmem=%~4 > nul is still needed. I found out that set /a skipmem= will always set the variable to zero. Which will be the case if optional argument %~4 is not in use.

 

As a side-note/OT question, the UUID generator uses the officially unofficial DOS algorithms, doesn't it? :unsure:

 

https://msfn.org/boa...&comment=980297

 

https://msfn.org/boa...#comment-987748

 

A couple small nitpicks (at first sight)  in:

 

#1 You have duplicated the minute assignment, probably a copy/paste effect :unsure:

#2 I am not too convinced of the formula for reducing the random value into a 0<=x<=99 range  :dubbio: I have to think about it ...

 

:duff:

Wonko

 

P.S.: No, I confirm, dividing by 10/100/1000 doesn't give "random enough" results, you'd better get two digits, i.e. *something like*:

set smallsec=%@random::~-2%

or (to avoid possible leading 0, and get an actual numeric value)

set /a smallsec=1%@random::~-2%-100

or

set /a smallsec=1%@random::~-1%1%@random::~-1%-100

Yes, I red all that stuff, and other 'things' I could found. A while ago already. A MSFN-member, named Jaclaz, helped me a lot too. :worship:

I tried to use the DOS-stuff, but without the DOS hundreds-of-seconds, they are not available in Grub4Dos as far as I know. Using random-numbers instead will be still an aproxximation....

 

About:

#1 True - Copy/ paste should be abandoned...

#2 True. My arithmetical approach gives the first two digits (or in very seldom cases if %@random% is below 10 one digit). In the distribution there are too many (decimal) numbers between 12 and 25 (maximum is 32 767 according to steve6375's book). Although in practice the 'hundreds' can even be set to zero (by removing '#' on line #set /a smallsec= > nul - probably > nul is not needed in this case if debug is on, but will do no harm ).

 

Which Grub4Dos user will format two partitions in less than one second? Only if creating a bunch of memdrives with map --mem, or creating images, maybe.

 

It seems %@retval% needs about 20 milli-seconds to generate a new value (in 64-bits VBox, on my AMD Bulldozer-system), while MakeUuid takes about 0,3-0,5 ms (calculated from a 10 000-looptest). So probably a delay should be added too.

 

I tried your suggestion of smallsec=%@random::~-2% seems theoretical better (and more practical too: one line instead of three). A sample of 100 of these gave following distribution: 22 duplicates and 5 triplets (but 6 duplicates in the range of 90-98). I am not an expert, seems not bad to me.

 

Also a (dirty) 'print-screen' of all three possibilities with echo of \%result%: above based on seconds only, in the middle my %@random%-approach and below Wonko's (all Litte-Endian, ready for write FILE \%result%).

grub> makeuuid makeuuid 
2021-07-29 00:59:16
 \x20\x08\x1D\x17 \x20\x08\x1D\x17 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1
D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x
08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \
x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D
\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08\x1D\x18 \x20\x08 
\x1D\x18 \x20\x08\x1D\x18 
grub> makeuuid makeuuid 
2021-07-29 00:59:36
 \x20\x08\x35\x2B \x20\x08\x39\x2B \x20\x08\x2D\x2B \x20\x08\x46\x2B \x20\x08\x3
1\x2B \x20\x08\x34\x2B \x20\x08\x31\x20 \x20\x08\x32\x2B \x20\x08\x34\x2B \x20\x 
08\x2B\x2B \x20\x08\x32\x2B \x20\x08\x35\x2B \x20\x08\x48\x2B \x20\x08\x28\x2C \
x20\x08\x37\x2C \x20\x08\x2F\x2C \x20\x08\x3C\2C \x20\x08\x39\x2C \x20\x08\x79\
x2C \x20\x08\x3D\x2C \x20\x08\x55\x2C \x20\x08\x51\x2C \x20\x08\x2B\x2C \x20\x08
\x27\x2C \x20\x08\x3B\x2C 
grub> makeuuid makeuuid 
2021-07-29 01:00:38
 \xE5\x08\x7A\x2E \xE5\x08\x54\x2E \xE5\x08\x2E\x2E \xE5\x08\x50\x2E \xE5\x08\x1 
F\x2E \xE5\x08\x5E\x2E \xE5\x08\x72\x2E \xE5\x08\x4E\x2E \xE5\x08\x37\x2E \xE5\x
08\x40\x2E \xE5\x08\x45\x2E \xE5\x08\x53\x2E \xE5\x08\x49\x2E \xE5\x08\x40\x2E \
xE5\x08\x1F\x2E \xE5\x08\x72\x2E \xE5\x08\x53\x2E \xE5\x08\x41\x2E \xE5\x08\x38
\x2E \xE5\x08\x45\x2E \xE5\x08\x3B\x2E \xE5\x08\x41\x2E \xE5\x08\x27\x2E \xE5\x08
\x26\x2E \xE5\x08\x45\x2E 
grub>

BTW for easy-going experimentation I changed to a .G4D-file, with loop and beep 0 20


Edited by deomsh, 3 days ago.


#82 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 3 days ago

You can still ADD a 0 in the place of the "optional" (not anymore optional) parameter.

I.e. (in my perverted mind) something *like*:

 

:CleanMd

call AllFunctions.lll %0 %* 0

goto :eof

 

could do nicely, if the (optional) parameter is specified on original call, it will be %4 (or %5, unless you use shift to have parameters as in the original call), if it is not specified the trailing 0 will "shift" and take its place.

 

About randomness, (actually pseudo-randomness) it is one of those topics that can be debated at length (not that it actually matters in this particular use).

 

For what it matters you could also use the canonical xkcd algorithm ;) :

https://xkcd.com/221/

 

 

The:

set /a smallsec=1%@random::~-2%-100

on second thought is not good as the value of @random may well be <=9 (or a single digit if you prefer) :dubbio: this possibility should be taken into account.

But if we take the digits "from the left", it can work, though,  as there will be no leading 00's and we can ignore the string length, i.e.:
set /a smallsec=%@random::~0,2%

 

The:

set /a smallsec=1%@random::~-1%1%@random::~-1%-100

is correct[1], as the @random can never have a <0 value, and it is still a single line, though it will be slightly slower so it is probably overkill.

 

 

:duff:

Wonko

 

 

[1] and essentially amounts to throwing two 10 side dices:

https://en.wikipedia...l_trapezohedron



#83 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted A day ago


For what it matters you could also use the canonical xkcd algorithm ;) :

https://xkcd.com/221/

Very nice, I should make a MakeRandom-function for xkcd :lol:

 


The:

set /a smallsec=1%@random::~-2%-100

on second thought is not good as the value of @random may well be <=9 (or a single digit if you prefer) :dubbio: this possibility should be taken into account.

This is not a problem in MAKEUUID.LLL, everything is counted and transformed with the textual approach. Values in the whole 0-99 range are processed, I hope in the right way.

 

I made a new version, with arguments this time, and I changed the name of the Function to MakeUuidFat. Output-format can be chosen, date/time/hundreth can be added if a certain MS-DOS UUID is wanted.

!BAT
#MAKEUUID.LLL v0.1.3 (20210730), by deomsh
#Generate MS-DOS Volume Serial Number
#Use: MAKEUUID.LLL MakeUuidFat [uuid|write] [year-month-day] [hour:minute:second] [hundreth]
#Mandarory Argument: MakeUuid
#Optional arguments: [uuid|write] [yyyy-mm-dd] [hh:mm:ss] [hundreth] (of seconds - default=0)
#Remarks: Function-name is not case-sensitive. [uuid|write] not case-sensitive, can be left out. If used: date time hundreth only last argument can be left out, their order is NOT free
call :%~1 %*
#echo %~1: result=%result%
goto :eof

:MakeUuidFat
setlocal && set *
if not /i "%~2"=="write" && if not /i "%~2"=="uuid" && set mode=uuid
if /i "%~2"=="write" && set mode=%~2 && shift
if /i "%~2"=="uuid" && set mode=%~2 && shift
set date=%~2
set time=%~3
set smallsec=%~4
if not exist date && set date=%@date%
set /a year=%date:~0,4% > nul
set /a month=%date:~5,2% > nul
set /a day=%date:~8,2% > nul
if not exist time && set time=%@time%
set /a hour=%time:~0,2% > nul
set /a minute=%time:~3,2% > nul
set /a second=%time:~6,2% > nul
if exist smallsec && set /a smallsec=%smallsec% > nul && goto :norandom
beep 0 20 ;; set /a smallsec=%@random:~-2% > nul
:norandom
#echo Date: %day%-%month%-%year% Time: %hour%:%minute%:%second%:%smallsec%
set /A month=%date:~5,2% * 0x100  > nul
set /A second=%time:~6,2% * 0x100 > nul
set /A uuidlow=%month% + %day% + %second% + %smallsec% > nul
set /a llow=%@retval% > nul
set /A hour=%time:~0,2% * 0x100 > nul
set /A uuidhigh=%hour% + %minute% + %year% > nul
set /a lhigh=%@retval% > nul
if %lhigh%==6 && if %llow%==6 && set volumeid=\x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul && set volserial=%uuidlow:~2,2%%%uuidlow:~4,2%%-%uuidhigh:~2,2%%%uuidhigh:~4,2%
if %lhigh%==6 && if %llow%==5 && set volumeid=\x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul && set volserial=0%uuidlow:~2,1%%%uuidlow:~3,2%%-%uuidhigh:~2,2%%%uuidhigh:~4,2%
if %lhigh%==5 && if %llow%==6 && set volumeid=\x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul && set volserial=%uuidlow:~2,2%%%uuidlow:~4,2%%-0%uuidhigh:~2,1%%%uuidhigh:~3,2%
if %lhigh%==5 && if %llow%==5 && set volumeid=\x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul && set volserial=0%uuidlow:~2,1%%%uuidlow:~3,2%%-0%uuidhigh:~2,1%%%uuidhigh:~3,2%
if %lhigh%==4 && if %llow%==6 && set volumeid=\x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul && set volserial=0%uuidlow:~1,2%%%uuidlow:~4,2%%-00%uuidhigh:~3,2%
if %lhigh%==4 && if %llow%==5 && set volumeid=\x%uuidhigh:~2,2%\x00\x0%uuidlow:~4,1%\x0%uuidlow:~2,1% > nul && set volserial=0%uuidlow:~2,1%%%uuidlow:~3,2%%-00%uuidhigh:~2,2%
if %lhigh%==3 && if %llow%==6 && set volumeid=\x00\x0%uuidhigh:~2,1%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul && set volserial=%uuidlow:~2,2%%%uuidlow:~4,2%%-000%uuidhigh:~2,1%
if %lhigh%==3 && if %llow%==5 && set volumeid=\x00\x0%uuidhigh:~2,1%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul && set volserial=0%uuidlow:~2,1%%%uuidlow:~3,2%%-000%uuidhigh:~2,1%
#echo Volume Serial Number: %volserial%
#echo Volume Serial Number little-endian: %volumeid% (for write FILE %^result%)
if %mode%==uuid && set result=%volserial% ! set result=%volumeid%
endlocal && set result=%result%
goto :eof

BTW: this version should be clean now (only a few echos left, can be activated if desired). I added lines to cope with years closer to 1 AD

 

After restudying Craig Wilson's 'Volume Serial Numbers' I added his '2003-10-19 22:33:27:1' example, together with use of other arguments in following 'print-screen':

grub> makeuuid.lll makeuuidFAT
date: 30-7-2021 time: 23:51:48:22
Volume Serial Number: 3734-1F18
Volume Serial Number little-endian: \x18\x1F\x34\x37 (for write FILE %result%)
makeuuidFAT: result=3734-1F18
grub> 
grub> makeuuid.lll makeuuidFAT write 
date: 30-7-2021 time: 23:51:51:74 
Volume Serial Number: 3A68-1F18 
Volume Serial Number little-endian: \x18\x1F\x68\x3A (for write FILE %result%) 
makeuuidFAT: result=\x18\x1F\x68\x3A
grub> 
grub> makeuuid.lll makeuuidFAT 2003-10-19 22:33:27 1
date: 19-10-2003 time: 22:33:27:1 
Volume Serial Number: 2514-1DF4 
Volume Serial Number little-endian: \xF4\x1D\x14\x25 (for write FILE %result%)
makeuuidFAT: result=2514-1DF4 
grub> 
grub> makeuuid.lll makeuuidFAT write 0001-01-01 00:00:00 0 
date: 1-1-1 time: 0:0:0:0 
Volume Serial Number: 0101-0001
Volume Serial Number little-endian: \x00\01\x01\x01 (for write FILE %result5)
makeuuidFAT: result=\x00\x01\x01\x01 
grub> _

BTW the only strange thing in Craig Wilson's paper is that the MS-DOS UUID isn't written in Litte-Endian in the picture on page 4. I checked again and again, but with uuid --write (hd2,0) 2514-1DF4 I get with cat --hex --skip=0x27 --length=4 (hd2,0)+1 always F4 1D 14 25 ??

 

I played a bit with uuid's before 1987. After attaching the VHD I used in Vbox with Disk Management, Windows 10 happily found no errors and displayed with DIR in cmd 0101-0001 :blink:

 

You can still ADD a 0 in the place of the "optional" (not anymore optional) parameter.

I.e. (in my perverted mind) something *like*:

 

:CleanMd

call AllFunctions.lll %0 %* 0

goto :eof

 

could do nicely, if the (optional) parameter is specified on original call, it will be %4 (or %5, unless you use shift to have parameters as in the original call), if it is not specified the trailing 0 will "shift" and take its place.

 

Although not needed for CleanMd, the idea from your 'perverted mind' 'saved my day' last thursday. I was trying to set several default values in a function to count variables, so without adding variables before all variables are safely in memory. So THANK YOU VERY MUCH. Even your call starting with %0 inspired my to a new argument (starting %0 is not needed in my approach, the function is always %1 before shifting and can be linked endlessly with :%1 %*).

!BAT
#CNTVARS.LLL v0.1 (20210729), by deomsh.
#Function: Count number of variables 
#Mandatory Arguments: CntVars
#Optional Arguments: [mdbase sectors %0]
#Remarks: (if used ALL needed: base memory in 512 byte sectors -default=0x3000; needed sectors for maximum number of variables of max length, max 511 sectors - default=60; %0 must be a label or preceding colon must be added)
#debug 0
#echo %*
##call :SubRoutine %*
call :%~1 %* 0x3000 60 
#echo Function: %~1 result=%result%
goto :eof

:SubRoutine
#echo %~0 %*
#call :%~1 %* 0x3000 60
call :%~1 %* 0x3000 60 %0
goto :eof

:CntVars
#echo %~0 %*
echo -n > (md)%~2+%~3
set > (md)%~2+%~3
setlocal && set *
echo -n && call Fn.4 ;; set /A r=%@retval% > nul ;; set /a y=%r%>>8 > nul ;; set /a x=%r%&0xFF > nul
cat --locate=\x0A (md)%~2+%~3 > nul ;; set /a result=%@retval% > nul
echo -n > (md)%~2+%~3
:LoopCntVars
set ARG=%~4 &; if not "%ARG%"=="" &; if %ARG:~0,1%==: && set ARG4=%~4 ! shift && goto :LoopCntVars
if exist ARG4 && set "message=Number of variables=%result% in %ARG4%" ! set "message=Number of variables=%result%"
set "message=%message%" ;; set msglen=%@retval% > nul ;; set /a h=79-%msglen% > nul
call Fn.5 %h% 24 || echo -n $[0x0F]%message%
call Fn.5 %x% %y%
#set
endlocal
#endlocal && set result=%result%
goto :eof

BTW, best used with: CNTVARS.LLL CntVars optional arguments && pause. For instance I tested in my editline-project call cntvars.lll CntVars 0x3900 60 %0 && pause to get on the last line shifted to the right: Number of variables=40 in :editline (:editline is the central submenu sub-routine).

 

BTW2 Of course 60 is overkill, one variable including name and overhead will in the average not come above 20-25 chars, so 3 sectors will do in most cases.

 

BTW3 Not meant as stand-alone utility. Can be used, but after line 23 only with && pause

 

Question: I don't see any possibility to make more than one default value (in fact I used one optional argument, consisting of two or three values). Will that be somehow do-able?

 

 

 

 

 

 


Edited by deomsh, A day ago.


#84 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted A day ago

 

Question: I don't see any possibility to make more than one default value (in fact I used one optional argument, consisting of two or three values). Will that be somehow do-able?

I am not sure to understand the question (actually I am pretty sure I don't understand it), can you explain/make an example?

 

The Big vs. Little Endian question is always the same one, it is easy to make confusion.

 

in Craig Wilson's paper page 4 he shows a hex/view where the sequence of bytes is

25 14 1D F4

then he proceeds to state that the volume label is 2514-1DF4 :w00t: :

 

Here is an example from a formatted FAT12 floppy diskette.

With reference to Figure 1 below, at offset 39 (0x27), you can see the hex values 25 14 1D F4 which is the Volume Serial Number.

With FAT32 volumes, the Volume Serial Number is stored in the Boot Sector at offset 67 (0x43).

When formatted, this floppy diskette returned the volume serial 2514-1DF4.

BUT on page 5, there is figure 3 where it is evident:

Volume Serial Number is F41D-1425

 

that the VOL utility (like - say - WMI) interprets the bytes sequence as Big Endian.

 

Using my little date_from_volser sheet (which has limits to the values you can attribute to the bytes) and that uses the hex dump sequence, it is evident how the serial stated on page 4 is actually the hex dump separated in two words by a hyphen :w00t: and NOT the actual serial as returned by MS tools.

 

:duff:

Wonko



#85 deomsh

deomsh

    Member

  • Members
  • 50 posts
  •  
    Netherlands

Posted 14 hours ago

First about the MS-DOS UUID only, I will later give a more lengthy version of my question regarding %*.

In Craig Wilson's paper, figure 1 on page 4 and figure 3 on page 5 seems to me fully consistent. I used the formula of figure 2 on page 5, interpreted in the Big-Endian order. Did you mean there is anything wrong with the order in the formula?

If 2514-1DF4 is written with Grub4Dos uuid to a FAT-partition, MS-DOS' VOL and DIR returns 2514-1DF4, and on disk is written in the PBR F4 1D 14 25. So Little-Endian order...

#86 Wonko the Sane

Wonko the Sane

    The Finder

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

Posted 27 minutes ago

The confusion, as often happens, is how you interpret the data and how you call it, by definition (or actually derived definition), a volume serial (or uuid) is *whatever* is returned by the VOL command (or the uuid one), consisting in two bytes, a hyphen and other two bytes, coming from a 4 bytes sequence in the bootsector that is written as a Big Endian 32 bit value..

 

The actual data in the paper (4 hex bytes sequence written to the volume serial location) is 25 14 1D F4.

The volume serial (as returned by the VOL command) is F41D-1425. <- this is the ONLY thing that you can properly call "Volume Serial" or "UUID"

 

It is clear that the VOL command does two operations:
1) interprets the 4 bytes as a Big Endian hex number
2) divides it in two two bytes words and inserts a hyphen between them

 

The uuid command in grub4dos does exactly the same as the VOL command (evidently to be consistent with it).

 

Quick example from a floppy:

uuid (fd0)

(fd0): UUID is "0AC4-AF63"

Filesystem type is FAT12, using all disk

 

cat --hex --skip=39 --length=4 (fd0)+1

00000026: 63 AF C4 0A

 

Your example implementation is seemingly "wrong" (i.e. reversed):

 

grub> makeuuid.lll makeuuidFAT 2003-10-19 22:33:27 1
date: 19-10-2003 time: 22:33:27:1
Volume Serial Number: 2514-1DF4
Volume Serial Number little-endian: \xF4\x1D\x14\x25 (for write FILE %result%)
makeuuidFAT: result=2514-1DF4

 

as what is actually written to disk (in the paper) is the sequence "25 14 1D F4" that is read by *any* VOL/UUID command as "F41D-1425".

 

There is a known (similar but fun) issue (JFYI) with Disk Signature on NT systems (JFYI).

 

The 4 bytes sequence at offset 440 in the MBR is (example):

59 AE 59 AE

 

If you go to HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices and look for the drive letter(s) assigned to the volume(s) on the disk, you will find something *like*:

\DosDevices\D: with value 59 AE 59 AE 00 7E 00 00 00 00 00 00

which basically means "the volume to which drive letter D: is assigned is on the disk with byte sequence at the disk signature offset of "59 AE 59 AE" and begins at offset 0x7E00".

 

You can use Diskpart to retrieve this info, *like*:

diskpart

select disk 1

detail disk

and you will obtain:

Disk ID: AE59AE59

 

So, the "Disk ID" is seemingly a Big Endian number (though in a number of places, including some of my old posts, it is likely that you will find the bytes sequence "!as is" called "disk signature").

 

Here is the fun part, we can get it also via WMI/wmic:

wmic DiskDrive get DeviceId, Signature
DeviceID Signature
\\.\PHYSICALDRIVE0 -1740662721
\\.\PHYSICALDRIVE1 -1369854375
...

Converting -1369854375 decimal to hex we get: FFFFFFFFAE59AE59

 

So, generally speaking the Disk Signature being a largely undocumented field, can be interpreted "as is" or as a Big Endian number by various different tools (and remember that Diskpart is a relatively recent tool, before it there wasn't AFAICT a MS original way to get that field).

 

And still two different tools by the same good MS guys call the same field "Disk Id" or "Signature" and return different values.

 

:duff:

Wonko







Also tagged with one or more of these keywords: grub4dos

5 user(s) are reading this topic

1 members, 4 guests, 0 anonymous users


    Wonko the Sane