RE: Re: [PATCH v2 3/3] efi: Capsule update with user helper interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Kweh, Hock Leong
> Sent: Tuesday, February 24, 2015 6:54 PM
> 
> In callbackfn_efi_capsule, you call request_firmware_nowait.  When that
> callback is invoked, I think that the /sys/class/firmware/efi-capsule-file
> directory doesn't exist at all.
> If the callback takes longer than it takes your script to make it through a full
> iteration, then it will try uploading the second capsule before the firmware
> class directory is there, so it will fail.
> 
> But I just realized that your script has a loop below to handle that.
> It's this:
> 
>                  oldtime=$(date +%S)
>                  oldtime=$(((time + 2) % 60))
>                  until [ -f /sys/class/firmware/efi-capsule-file/loading ]
>                  do
>                          newtime=$(date +%S)
>                          if [ $newtime -eq $oldtime ]
>                          then
>                                  break
>                          fi
>                  done
> 
> Aside from the fact that this loop itself is racy (it may loop forever if
> something goes wrong in the kernel, since $newtime -eq $oldtime may
> never happen), it should help, if you're lucky.  But there's another bug.
> 
> 
> Here's the race:
> 
> User:
> echo 1 > /sys/class/firmware/efi-capsule-file/loading
> cat capsule1 > /sys/class/firmware/efi-capsule-file/data
> echo 0 > /sys/class/firmware/efi-capsule-file/loading
> Kernel: Be a little slow here due to preemption or whatever.
> 
> User:
> -f /sys/class/firmware/efi-capsule-file/loading returns true capsules_loaded
> == 0 Assume failure, incorrectly
> 
> Kernel: catch up and increment capsules_loaded.
> 
> If these patches get applied, then I think that the protocol needs to be
> documented in Documentation/ABI.  It should say something like:
> 
> To upload an EFI capsule, do this:
> 
> Write 1 to /sys/class/firmware/efi-capsule-file/loading
> Write the capsule to /sys/class/firmware/efi-capsule-file/data
> Write 0 to /sys/class/firmware/efi-capsule-file/loading
> 
> Make sure that /sys/class/firmware/efi-capsule-file disappears and comes
> back, perhaps by cd-ing there and waiting for all the files in the directory to
> go away.
> 
> Then, and only then, read capsules_loaded to detect success.
> 
> 
> Once you've written that doc, please seriously consider whether this
> interface is justifiable.  I think it sucks.
> 
> --Andy

Hi All,

After some internal discussion and re-design prototyping & testing on
this efi capsule interface kernel module, I would like to start a discussion
here on the new idea and wish to get input for the implementation and
eventually upstream.

This new idea will expose 2 read-only file notes from the efi capsule kernel
module - "capsule_ticket" and "capsule_report". The "capsule_ticket" will
let user to obtain a NON-ZERO number and then perform a mutex lock. The
obtained number will be used later for "capsule_report" status checking.
Unlock mutex is done after "echo 0 > loading" at the end of callback function.

So the process steps basically look like this:
1.) cat capsule_ticket    =======> acquire a number and lock mutex then
                                                                     expose firmware_class user helper
                                                                     interface as well as start timer for timeout
                                                                     counting
2.) repeat step 1 if obtained a "0" number
3.) echo 1 > loading
4.) cat bin > data
5.) echo 0 > loading        =======> stop the timeout counting  then unlock
                                                                      mutex at the end of callback routine 
6.) cat capsule_report   =======> grep the number acquired from beginning
                                                                      for checking succeeded/failed

The ticket numbering is starting from 1 to 999 and then rolls over from
1 to 999 again. The "capsule_report" will show the whole list of the acquired
entries and will be limited to 128 entries which is capped within one page buffer.

The format of this "capsule_report" output will look like:
"Capsule $num uploads successful/failed/aborted"

There is a 2mins time out (internal) for each of the number acquired.
After that, the interface will be closed/disappeared.

I have attached a SAMPLE script and kernel module code in case you are not
able to understand my description above.

I believe this would really take care of the multi-capsule update concurrently
issue and also asynchronous status reporting issue. Besides, this will indirectly
take care the module unload issue with "rmmod" and not "rmmod -f".
What do you guys think?

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

There is another idea during internal discussion. The 2nd idea would require
some changes to drivers/base/firmware_class.c user helper interface for the
mutex locking as well as status return. Mutex lock will be performed while
doing the 'echo 1 > loading' session and status return will be performed after
the 'echo 0 > loading'. The mutex unlock will be done at 'echo 0 > loading' too
or may be at the status reading session for avoid asynchronous reporting.

This will likely changed the original firmware class user helper interface design
behavior. But this approach could save the 2 file notes from the 1st approach.


Which of the approach do you guys prefer? Thanks.


Regards,
Wilson

#!/bin/sh

for arg in "$@"
do
	if [ -f $arg ]
	then
		retry=0
		until [ ! $num = '0' ]
		do
			sleep 1
			num=$(cat /sys/devices/platform/efi_capsule_user_helper/capsule_ticket)
			if [ $retry -le 130 ]
			then
				retry=$((retry + 1))
			else
				echo "Failed to acquire capsule ticket"
				exit 1
			fi
		done

		oldtime=$(date +%S)
		oldtime=$(((time + 2) % 60))
		until [ -f /sys/class/firmware/efi-capsule-file/loading ]
		do
			newtime=$(date +%S)
			if [ $newtime -eq $oldtime ]
			then
				echo "Failed to expose user helper interface"
				exit 1
			fi
		done

		echo 1 > /sys/class/firmware/efi-capsule-file/loading
		cat $arg > /sys/class/firmware/efi-capsule-file/data
		echo 0 > /sys/class/firmware/efi-capsule-file/loading

		until [ -n "$result" ]
		do
			result=$(cat /sys/devices/platform/efi_capsule_user_helper/capsule_report | grep $num)
		done
		echo $result " (" $arg ")"
	else
		echo "File $arg not found !!"
	fi
done
exit 0

Attachment: 0002-efi-Capsule-update-with-user-helper-interface.patch
Description: 0002-efi-Capsule-update-with-user-helper-interface.patch


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux