Skip to content

Commit dc96177

Browse files
committed
Fix bugs in esp32 mkimage.erl script
Fixes an FD leak, the image file was never closed properly after writing. Fixes a misleading error message when a binary overlows its partiton. Closes #2084 Signed-off-by: Winford <winford@object.stream>
1 parent aa7ac0f commit dc96177

1 file changed

Lines changed: 58 additions & 52 deletions

File tree

src/platforms/esp32/tools/mkimage.erl

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -135,62 +135,68 @@ mkimage(RootDir, BootFile, OutputFile, Segments) ->
135135
io:format("=============================================~n"),
136136
case file:open(OutputFile, [write, binary]) of
137137
{ok, Fout} ->
138-
lists:foldl(
139-
fun(Segment, PrevOffset) ->
140-
SegmentOffset = from_hex(maps:get(offset, Segment)),
141-
case PrevOffset of
142-
undefined ->
143-
no_padding;
144-
_ ->
145-
case SegmentOffset > PrevOffset of
146-
true ->
147-
Padding = [
148-
16#FF
149-
|| _ <- lists:seq(1, SegmentOffset - PrevOffset)
150-
],
151-
io:format("Padding ~p bytes~n", [SegmentOffset - PrevOffset]),
152-
file:write(Fout, Padding);
153-
false ->
154-
throw(
155-
io_lib:format(
156-
"Error: insufficient space for segment ~p. Over by: ~p bytes~n",
157-
[
158-
maps:get(name, Segment), PrevOffset - SegmentOffset
159-
]
160-
)
161-
)
162-
end
163-
end,
164-
SegmentPaths = [
165-
replace(
166-
"BOOT_FILE", BootFile, replace("ROOT_DIR", RootDir, SegmentPath)
167-
)
168-
|| SegmentPath <- maps:get(path, Segment)
169-
],
170-
case try_read(SegmentPaths) of
171-
{ok, Data} ->
172-
file:write(Fout, Data),
173-
io:format("Wrote ~s (~p bytes) at offset ~s (~p)~n", [
174-
maps:get(name, Segment),
175-
byte_size(Data),
176-
maps:get(offset, Segment),
177-
SegmentOffset
178-
]),
179-
SegmentOffset + byte_size(Data);
180-
{error, Reason} ->
181-
Fmt =
182-
"Failed to read file ~p Reason: ~p."
183-
" Note that a full build is required before running this command.",
184-
throw(io_lib:format(Fmt, [SegmentPaths, Reason]))
185-
end
186-
end,
187-
undefined,
188-
Segments
189-
);
138+
write_segments(RootDir, BootFile, Fout, Segments);
190139
{error, Reason} ->
191140
throw(io_lib:format("Failed to open ~s for writing. Reason: ~p", [OutputFile, Reason]))
192141
end.
193142

143+
%% @private
144+
write_segments(RootDir, BootFile, Fout, []) ->
145+
file:close(Fout);
146+
write_segments(RootDir, BootFile, Fout, [Segment | Segments]) ->
147+
SegmentOffset = from_hex(maps:get(offset, Segment)),
148+
SegmentPaths = [
149+
replace(
150+
"BOOT_FILE", BootFile, replace("ROOT_DIR", RootDir, SegmentPath)
151+
)
152+
|| SegmentPath <- maps:get(path, Segment)
153+
],
154+
SegmentEnd = case try_read(SegmentPaths) of
155+
{ok, Data} ->
156+
file:write(Fout, Data),
157+
io:format("Wrote ~s (~p bytes) at offset ~s (~p)~n", [
158+
maps:get(name, Segment),
159+
byte_size(Data),
160+
maps:get(offset, Segment),
161+
SegmentOffset
162+
]),
163+
SegmentOffset + byte_size(Data);
164+
{error, Reason} ->
165+
Fmt =
166+
"Failed to read file ~p Reason: ~p."
167+
" Note that a full build is required before running this command.",
168+
throw(io_lib:format(Fmt, [SegmentPaths, Reason]))
169+
end,
170+
if Segments == [] -> ok;
171+
true ->
172+
[PeekNext | _] = Segments,
173+
NextOffset = from_hex(maps:get(offset, PeekNext)),
174+
case SegmentEnd > NextOffset of
175+
true ->
176+
throw(
177+
io_lib:format(
178+
"Error: insufficient space for segment ~p. Overflows partition by: ~p bytes~n",
179+
[maps:get(name, Segment), SegmentEnd - NextOffset]
180+
)
181+
);
182+
false ->
183+
PadSize = NextOffset - SegmentEnd,
184+
case PadSize of
185+
0 ->
186+
ok;
187+
PadSize ->
188+
Padding = [
189+
16#FF
190+
|| _ <- lists:seq(1, PadSize)
191+
],
192+
io:format("Padding ~p bytes~n", [PadSize]),
193+
file:write(Fout, Padding),
194+
ok
195+
end
196+
end
197+
end,
198+
write_segments(RootDir, BootFile, Fout, Segments).
199+
194200
%% @private
195201
try_read([]) ->
196202
{error, not_found};

0 commit comments

Comments
 (0)